Raspberry PI 3 + Motorsteuerung

Last Updated on 10. Oktober 2026 by sfambachLink-Status: OK

Ziel ist es, mit dem Raspberry PI 3 unter Zuhilfenahme einer Motorbrücke 2 Gleichstrommotoren zu betreiben.

Dies soll später genutzt werden, um einen zweirädrigen Roboter anzutreiben.


Hardware

PI3 (oder älter, bitte auf die richtigen Pins achten)
Motorbrücke L9110sLink-Status: OK
2x DC Motor
Diverse Kabel ( Vorgefertigte Pin-Header Kabel)


Testaufbau

GPIOs am Raspberry

  • Motor1 Richtung GPIO 26
  • Motor1 Geschwindigkeit GPIO 1
  • Motor2 Richtung GPIO 24
  • Motor3 Geschwindigkeit GPIO 23

(Die GPIOs gelten nur in Verbindung mit pi4j und wirePi)

Plan


Software

Entwicklungsumgebung

Als Entwicklungsumgebung verwende ich BlueJ auf dem PI selbst. Hiermit habe ich vier Klassen erstellt. Diese werden im folgenden Abschnitt kurz erklärt.


Code

Da ich anfänglich ein paar Probleme hatte und die Motorbrücke nicht wie erwartet reagierte, habe ich mich langsam an das Thema herangetastet.

Digitale Ansteuerung

Zuerst habe ich eine kleine Testklasse geschrieben, welche die Motoren digital ansteuert. Hiermit konnte ich die richtige Verkabelung sicherstellen. Mit diesem Test ist noch keine Geschwindigkeitsregulierung möglich.

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 MotorDigitalTest.java

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;

/**
 * Digitaler Test der Motorbrücke L9110S: beide Motoren vor, Stopp, zurück.
 * Motor 1: Richtung GPIO 26, Geschwindigkeit GPIO 1
 * Motor 2: Richtung GPIO 24, Geschwindigkeit GPIO 23 (pi4j / WiringPi-Nummerierung)
 * www.fambach.net, GPLv2
 */
public class MotorDigitalTest {

    public static void main(String[] args) throws InterruptedException {
        GpioController gpio = GpioFactory.getInstance();
        GpioPinDigitalOutput dir1 = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_26, "M1 Richtung", PinState.LOW);
        GpioPinDigitalOutput speed1 = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_01, "M1 Geschwindigkeit", PinState.LOW);
        GpioPinDigitalOutput dir2 = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_24, "M2 Richtung", PinState.LOW);
        GpioPinDigitalOutput speed2 = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_23, "M2 Geschwindigkeit", PinState.LOW);

        for (GpioPinDigitalOutput pin : new GpioPinDigitalOutput[] {dir1, speed1, dir2, speed2}) {
            pin.setShutdownOptions(true, PinState.LOW);
        }

        System.out.println("Vorwärts");
        dir1.low();
        speed1.high();
        dir2.low();
        speed2.high();
        Thread.sleep(2000);

        System.out.println("Stopp");
        speed1.low();
        speed2.low();
        Thread.sleep(1000);

        // Bei L9110S kehrt sich die Richtung um, wenn beide Eingänge getauscht werden
        System.out.println("Rückwärts");
        dir1.high();
        speed1.low();
        dir2.high();
        speed2.low();
        Thread.sleep(2000);

        System.out.println("Stopp");
        dir1.low();
        dir2.low();
        gpio.shutdown();
    }
}

PWM Ansteuerung

Als Nächstes habe ich eine Testklasse erstellt, die den Hardware PWM benutzt und ebenfalls die Richtungen wechselt.

Quellcode MotorPwmTest.java

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.GpioPinPwmOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;
import com.pi4j.wiringpi.Gpio;

/**
 * Test der Motorbrücke L9110S mit Hardware-PWM (GPIO 1 und GPIO 23)
 * in beiden Richtungen und verschiedenen Geschwindigkeiten.
 * www.fambach.net, GPLv2
 */
public class MotorPwmTest {

    private static final int RANGE = 1024;

    public static void main(String[] args) throws InterruptedException {
        GpioController gpio = GpioFactory.getInstance();
        GpioPinDigitalOutput dir1 = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_26, "M1 Richtung", PinState.LOW);
        GpioPinDigitalOutput dir2 = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_24, "M2 Richtung", PinState.LOW);
        GpioPinPwmOutput speed1 = gpio.provisionPwmOutputPin(RaspiPin.GPIO_01, "M1 Geschwindigkeit", 0);
        GpioPinPwmOutput speed2 = gpio.provisionPwmOutputPin(RaspiPin.GPIO_23, "M2 Geschwindigkeit", 0);

        Gpio.pwmSetMode(Gpio.PWM_MODE_MS);
        Gpio.pwmSetRange(RANGE);
        Gpio.pwmSetClock(50);

        int[] speeds = {256, 512, 768, 1024};

        System.out.println("Vorwärts");
        dir1.low();
        dir2.low();
        for (int speed : speeds) {
            System.out.println("Geschwindigkeit " + speed);
            speed1.setPwm(speed);
            speed2.setPwm(speed);
            Thread.sleep(1500);
        }

        // Rückwärts: Richtungspin high, PWM invertiert
        System.out.println("Rückwärts");
        dir1.high();
        dir2.high();
        for (int speed : speeds) {
            System.out.println("Geschwindigkeit " + speed);
            speed1.setPwm(RANGE - speed);
            speed2.setPwm(RANGE - speed);
            Thread.sleep(1500);
        }

        System.out.println("Stopp");
        speed1.setPwm(0);
        speed2.setPwm(0);
        dir1.low();
        dir2.low();
        gpio.shutdown();
    }
}

Funktionalität in Klasse gepackt

Als letzten Schritt habe ich eine Klasse Drive zur Steuerung beider Motoren und die dazu gehörende Testklasse erstellt.

Drive Klasse

Klasse zur Steuerung der zwei Motoren.

Quellcode Drive.java

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.GpioPinPwmOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;
import com.pi4j.wiringpi.Gpio;

/**
 * Steuert zwei Gleichstrommotoren über die Motorbrücke L9110S.
 * Geschwindigkeit 0..100 %, Richtung vorwärts/rückwärts je Motor.
 * www.fambach.net, GPLv2
 */
public class Drive {

    private static final int RANGE = 1024;

    private final GpioController gpio;
    private final GpioPinDigitalOutput dirLeft;
    private final GpioPinDigitalOutput dirRight;
    private final GpioPinPwmOutput speedLeft;
    private final GpioPinPwmOutput speedRight;

    public Drive() {
        gpio = GpioFactory.getInstance();
        dirLeft = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_26, "Links Richtung", PinState.LOW);
        dirRight = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_24, "Rechts Richtung", PinState.LOW);
        speedLeft = gpio.provisionPwmOutputPin(RaspiPin.GPIO_01, "Links Geschwindigkeit", 0);
        speedRight = gpio.provisionPwmOutputPin(RaspiPin.GPIO_23, "Rechts Geschwindigkeit", 0);

        Gpio.pwmSetMode(Gpio.PWM_MODE_MS);
        Gpio.pwmSetRange(RANGE);
        Gpio.pwmSetClock(50);
    }

    public void forwardLeft(int percent) {
        dirLeft.low();
        speedLeft.setPwm(toPwm(percent));
    }

    public void backwardLeft(int percent) {
        dirLeft.high();
        speedLeft.setPwm(RANGE - toPwm(percent));
    }

    public void forwardRight(int percent) {
        dirRight.low();
        speedRight.setPwm(toPwm(percent));
    }

    public void backwardRight(int percent) {
        dirRight.high();
        speedRight.setPwm(RANGE - toPwm(percent));
    }

    public void forward(int percent) {
        forwardLeft(percent);
        forwardRight(percent);
    }

    public void backward(int percent) {
        backwardLeft(percent);
        backwardRight(percent);
    }

    /** Auf der Stelle drehen */
    public void turnLeft(int percent) {
        backwardLeft(percent);
        forwardRight(percent);
    }

    public void turnRight(int percent) {
        forwardLeft(percent);
        backwardRight(percent);
    }

    public void stop() {
        dirLeft.low();
        dirRight.low();
        speedLeft.setPwm(0);
        speedRight.setPwm(0);
    }

    public void shutdown() {
        stop();
        gpio.shutdown();
    }

    private static int toPwm(int percent) {
        int limited = Math.max(0, Math.min(100, percent));
        return limited * RANGE / 100;
    }
}

Test-Drive Klasse

Klasse zum Testen der Motoren. Diese testet, wie auch im vorhergehenden Beispiel,  unterschiedliche Geschwindigkeiten und Richtungen.

Quellcode DriveTest.java

/**
 * Testet die Klasse Drive mit verschiedenen Geschwindigkeiten und Richtungen.
 * www.fambach.net, GPLv2
 */
public class DriveTest {

    public static void main(String[] args) throws InterruptedException {
        Drive drive = new Drive();

        for (int speed = 25; speed <= 100; speed += 25) {
            System.out.println("Vorwärts " + speed + " %");
            drive.forward(speed);
            Thread.sleep(1500);
        }
        drive.stop();
        Thread.sleep(1000);

        for (int speed = 25; speed <= 100; speed += 25) {
            System.out.println("Rückwärts " + speed + " %");
            drive.backward(speed);
            Thread.sleep(1500);
        }
        drive.stop();
        Thread.sleep(1000);

        System.out.println("Links drehen");
        drive.turnLeft(50);
        Thread.sleep(1500);

        System.out.println("Rechts drehen");
        drive.turnRight(50);
        Thread.sleep(1500);

        drive.shutdown();
    }
}

Tipps

Es geht nix

Es gibt verschiedene Shell Implementierungen, mit deren Hilfe ihr die IOs einfach mal schalten könnt.

Stellt den direction Port jeweils auf Low und den Speed Port auf high, dann sollte sich was tun.

Hilfe zur Shell-Bedienung findet ihr hier:
https://www.elektronik-kompendium.de/sites/raspberry-pi/2006041.htmLink-Status: OK

Für Motor 1 sähe das in sysfs in etwa so aus

Ausgaberichtung setzen

echo out > /sys/class/gpio/gpio26/direction
echo out > /sys/class/gpio/gpio1/direction

Motoren schalten

echo 0 > /sys/class/gpio/gpio26/value
echo 1 > /sys/class/gpio/gpio1/value

Achtung: Bitte überprüfen, ob das mit den Gpio Ports so stimmt, evtl. könnten die Zahlen abweichen.

Motoren drehen nicht in die richtige Richtung

Sollten die Motoren nicht in die richtige Richtung drehen, einfach die Polarität am Anschluss an der Motorbrücke vertauschen, bis es passt. Sollte das nicht möglich sein, die Methoden forwardLeft/Right() und backwardLeft/Right() entsprechend anpassen.

Raspberry rebooted bei Aktivierung/Betrieb der Motoren

Sollte beim Einschalten/Betrieb der Motoren der Raspberry neu booten, kann dies am hohen Stromverbrauch der Motoren liegen. Dann sollte man überlegen, die Motoren entweder über eine zusätzliche Spannungsquelle zu versorgen oder zumindest die Motoren mit einer Spule zu entstören. Kondensatoren können zusätzlich Spannungsspitzen abfangen.

Mehr zur Entstörung:

http://www.bnhof.de/~ho1645/entstoer.htm
https://www.mikrocontroller.net/articles/Motoransteuerung_mit_PWM

Schaltung mit zusätzlicher Spannungsquelle:

Hier wird der L9110 mit einem LiPo versorgt, wichtig ist es, die Masse des Lipo mit der des Raspberries zu verbinden, sonst funktioniert es nicht. Der Lipo sollte im Bereich 3.7v und < 12V liegen (Beschränkung des L9110).


Quellen

Beispiel auf GitHubLink-Status: Kaputt
PI4j WebseiteLink-Status: OK
PWM + Motoren allgemein beim RoboterNetzLink-Status: OK

Einige andere Webseiten waren auch noch nützlich, einfach mal Google bemühen.

Verwandte Beiträge


Anhang

Pin-Belegung

http://www.pi4j.com
DatumÄnderungAutor
10.10.2026Verlorenen Gistpen-Code durch neu erstellten Code (Code-Blöcke) ersetztsfambach
08.10.2026Überschriften-Hierarchie korrigiert (H1→H2, Unterebenen eine Stufe tiefer)sfambach
04.10.2026Rechtschreibung korrigiert: Tippfehler, Kommas, Groß-/Kleinschreibungsfambach
03.10.2026Log-Liste eingefügtsfambach
14.06.2017Beitrag erstelltsfambach
Logbuch

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert