Mehrere Servo Motoren gleichzeitig per Raspberry Pi steuern (PCA9685)

Mittels PWM kann ein Servo Motor am Raspberry Pi gesteuert werden. Möchte man mehr als einen Servo Motor lenken, so kann man entweder für jeden der Servos einen GPIO nutzen oder ein Treiber Board wie das PCA9685 am Raspberry Pi anschließen, womit per I2C fast beliebig viele Motoren separat gesteuert werden können.

In Projekten wie einem Roboterarm ist ein solches Treiberboard für mehrere Servomotoren unumgänglich, auch da die Motoren einen recht hohen Strombedarf haben.

 

Zubehör

Bis zu 15 Servo Motoren können pro PCA9685 gesteuert werden.

Je nach Stärke der Motoren wird die Stromversorgung über die GPIOs der Raspberry Pi’s nicht ausreichen. Daher solltest du über ein externes Netzteil nachdenken. Dies kann entweder ein einstellbares oder z.B. ein Schaltnetzteil mit 5V (wie hier verwendet) sein.

Folgendes Zubehör solltest du für dieses Tutorial haben:

Achte bei deinem Netzteil, dass es genügend Power für alle Motoren hat. Wenn wir bspw. von 6 Motoren und ~500mA pro Motor ausgehen, so sollte es 3A liefern können. Da allerdings z.B. beim 6DOF Robot Arm nur selten alle 6 Motoren gleichzeitig laufen, sollte auch ein Netzteil mit weniger Stromstärke ausreichen.

Im Grunde ist die Anzahl der Motoren für dieses Projekt egal (bis zu 16 pro Board). Falls du vorläufig also nur einen Motor zur Hand hast, sollte dies dennoch ausreichen, da sich die Programmierung super einfach auf weitere Servos zu übertragen.

 

Raspberry Pi PCA9685 – I2C Adressierung

Das PCA9685 hat außerdem noch einige Lötkontakte, welche zum Festlegen der I2C Adresse gedacht sind. Ist kein Kontakt verlötet, so hat es die I2C Hex Adresse 0x40. Wenn mehrere dieser Boards verwendet werden sollen, muss jedes eine eigene Adresse bekommen. Dafür sind die Lötstellen, wobei die Nummerierung einem Binär Wert entspricht:

  • A0 = 2^0 (bspw. 41)
  • A1 = 2^1 (bspw. 42)

Somit könnten theoretisch bis zu 2^6 (= 64) der Boards hintereinander geschaltet werden und alle über Ihre eigene Adresse angesprochen werden. Und jedes der Boards kann ebenfalls 16 Servos steuern. Das sollte in jedem Fall ausreichen. Mehr Details dazu findest du u.a. im Datenblatt.

 

PCA9685 Anschluss an den Raspberry Pi

Das PCA9685 Modul wird über den I2C Bus gesteuert (SDA und SCL). Der Bus wird über 3.3V mit Strom versorgt, wobei die Power für die Motoren aus einer anderen Quelle kommt.

PCA9685 Raspberry Pi
SCL GPIO 3 / SCL (Pin 5)
SDA GPIO 2 / SDA (Pin 3)
VCC / V 3,3V (pin 1)
GND GND (Pin 6)

Die restlichen Pins (V+ und OE) bleiben unbelegt. Falls du mehr als ein I2C Modul nutzt, kannst du vom anderen Ende die anderen Module in Reihe anschließen.

Raspberry Pi mehrere Servos anschließen

Stärkere Servos wie der MG996R können bis zu 1.5A verbrauchen, weshalb eine externe Stromversorgung bei entsprechender Belastung bzw. bei mehreren Motoren sehr zu empfehlen. Bei einem oder zwei Servo Motoren kannst du die „externe“ Stromversorgung auch vom Raspberry Pi beziehen (üblicherweise wollen Servos ~5V). Der Strom reicht aber nicht für viele Servos, weshalb du z.B. beim Roboter Arm Projekt o.ä. auf eine externe Stromversorgung zurückgreifen solltest.

 

 

Installation der benötigten Tools

Öffne ein neues Terminal (z.B. per SSH) und gib folgendes ein:

sudo apt-get install build-essential python-dev python-smbus i2c-tools python-pip --yes

Falls Python3 genutzt werden soll, so müssen die Paketnamen natürlich entsprechend angepasst werden. Wir aktivieren zunächst I2C, sofern nicht schon geschehen:

sudo raspi-config

Unter „Interfacing Options“ -> „I2C“ wird es aktiviert. Wir schauen nun, ob das Board auch erkannt wird:

i2cdetect -y 1

Hier solltest du die Adresse des Boards sehen. Falls du die Adresspins verlötet hast, hast du ggf. eine andere Adressierung (wie oben beschrieben). Ansonsten sollte die Ausgabe folgend aussehen:

pi@raspberrypi:~ $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: 70 -- -- -- -- -- -- --

Anschließend installieren wir noch den Python Treiber für das Servo Board (wer den Code einsehen möchte bzw. lieber aus dem Repository installieren möchte, kann einen Blick in das GitHub Repo werfen). Einfacher ist es jedoch hiermit:

 sudo pip install Adafruit-PCA9685

 

Beispiele & Erklärung zur Nutzung des PCA9685 am Raspberry Pi

Alle folgenden Befehle sind in der Python Konsole auszuführen (sudo python) oder in ein entsprechendes Python Skript zu schreiben.

Zunächst einmal müssen wir die Bibliothek einbinden:

Als nächstes gilt es das PCA9685 Treiber Board zu initialisieren. Dabei hast du die Möglichkeit eine andere Adresse als 0x40 anzugeben, sofern gewünscht. Falls du den Parameter nicht angibst, wird automatisch 0x40 genommen:

Wie auch bei der gewöhnlichen PWM Steuerung über GPIOs müssen wir ebenfalls eine Frequenz angeben (in Hertz). Der Wert kann dabei zwischen 40 und 1000 liegen. Diese gilt für alle angeschlossenen Motoren:

Die gesendeten Impulse sind natürlich abhängig von der Frequenz und müssen ggf. angepasst werden.

Der zweite wichtige Befehl ist jener, mit dem wir den Puls für einen angeschlossenen Servo Motor senden. Der erste Parameter ist dabei der Channel (zw. 0 und 15), der zweite und dritte Parameter ist die relative Pulslänge im Verhältnis zu 4096 (was 2^12 entspricht). Die Differenz der beiden Werte darf nicht größer als 4096 sein.
Um den Motor in Stellung zu bringen können wir bspw. folgendes eingeben:

Dabei wird lediglich die Differenz berechnet. Der obige Aufruf ist also äquivalent zu diesem:

Das Signal wird im folgend berechnet: Möchtest du ein Signal von bspw. 0.5ms (=0.0005s) bei einer Frequenz von 50Hz (ein Puls ist 20ms breit) ausgeben, so müsste der relative Wert ~100 sein (50Hz * 0.0005s * 4096 = 102.4). Die üblichen Pulslängen von Servos sind 0.5ms (0°) bis 2.5ms (180°). Dazwischen wird interpoliert.

Wie auch im Beispiel des einfachen Servos gilt, dass wir das „Ruckeln“ des Servos ausstellen können, sofern wir den Puls auf Null setzen:

 

Wenn du ein vordefiniertes Beispiel testen möchtest, kannst du dies ebenfalls:

wget https://raw.githubusercontent.com/adafruit/Adafruit_Python_PCA9685/master/examples/simpletest.py

sudo python simpletest.py

Dieses Beispiel setzt die definierten Minimum / Maximum Signale, wodurch der Motor hin und Her rotiert.

 

Übrigens: Nicht nur Servos können mit diesem Board gesteuert werden. Auch LEDs oder andere Module, welche PWM nutzen, können damit sehr einfach angesprochen werden.

39 Kommentare

  1. Hallo,
    vielen Dank für diesen Beitrag.
    Zwei Fragen.
    1. Die Frequenz hast Du in der Erklärung bei 50 Hz angenommen, im Beispielcoding ist der Wert dann aber 60 Hz (macht vielleicht nichts am Ergebnis aus, aber wollte das nur verstehen).
    2. Die „Helper function“ wird nicht bei der Abarbeitung des Codes verwendet, oder?

    Eine Anmerkung:
    Wenn ein Servo z.B. das DS3218MG nur lahm ruckelt, dann liegt es daran dass das Netzteil mit z.B. 5V (800mA) zu schwach ist, dann helfen 6 V (1000 mA) wenn der PCA9685 verwendet wird.
    Gruß
    Dirk

    Antworten
    • Hallo Dirk,
      stimmt beides. In meinem Beispiel habe ich 50Hz genommen, die von Adafruit nehmen 60Hz und rufen die helper Funktiong gar nicht auf.
      Viele Grüße,
      Felix

      Antworten
  2. Hallo Felix,

    vielen Dank für das super Tutorial.
    Ich warte noch auf meine Servos und dann werde ich etwas mit dem PCA9685 experimentieren.
    Damit lassen sich sicher auch DC Motoren steuern oder?

    Antworten
  3. Hallo Felix,
    ich bin neu auf der Website. Bin Elektrotechniker im Ruhestand (seit 4 Monaten) und beschäftige mich seit ein paar Tagen mit Raspberry Pi. Ich habe die Hardware bestellt und warte darauf. Meine letzten Projekte (Zwei Roboterarme) hab ich mit Arduino realisiert. Deine Website in deutscher Sprache und zudem verständlich finde ich einfach toll. Bitte weiter so!

    Antworten
    • Hallo Erich,
      danke und viel Erfolg bei deinem Projekt 🙂 Demnächst kommt auch eine Anleitung, wie man einen Roboter Arm über einen Xbox Controller fernsteuern kann.
      LG, Felix

      Antworten
  4. Grüße . eine schöne Seite hast du hier gebastelt. Total gut.
    .
    Ich beschäftige mich nun schon einige Zeit mit dem RPi3 und diesem PCA9658.
    Jedoch kann ich mir keine Reim darauf machen wie man die Servos z.B.
    per Tastaur oder beser noch über einen Joystick ansteuern kann.
    Ich stelle mir vor das man eine bestimmte Taste eine bestimmte Zeit drückt und der Servo
    ebnso lange in eine bestimmte Richtung dreht.
    vieleicht könntest Du uns dazu einmal erleuchten.
    für den 6DOF RoboterArm were das ein großer gewinn
    LG Norbert

    Antworten
  5. wow danke für die schnelle Rückmeldung.
    Ich stelle mir letztlich einen 3d joystick vor.
    dein Controller-Tutorial sehe ich mir glei mal genauer an.
    Danke und mach weiter so.

    Grüße Norbert

    Antworten
  6. Guten Nachmittag

    Nachdem ich mir die Nacht um die Ohren geschlagen habe fährt mein Pi.Bot.
    (darauf soll der Greifarm später montirt werden)
    nun ,über Tastatur und XRDP, Vor Zurück Rechts und Links.
    (wie ich finde nicht schlecht für einen Anfänger)
    nun werde ich versuchen deinen Code runterzuladen
    Um mich damit auseinandersetzen.
    Und versuchen diesen auf mein Projekt anzuwenden.
    also auf den Joystick fertig los …

    DAnke Norbert

    Antworten
  7. hi ,bin neu hier coole sache habe gerade den Roboter arm bestelt.
    Aber kleine frage wie stellt man den kanall ein (mein alter 9 Jahre , 3 klasse)

    liebe grüsse Sebastian.

    Antworten
  8. PCA 9685 mit Python 3 nutzen

    Hallo Felix,
    erstmal Danke für das tolle Tutorial. Ich möchte den PCA 9685 mit Python 3 nutzen. Dazu heißt es:
    „Falls Python3 genutzt werden soll, so müssen die Packetnamen natürlich entsprechend angepasst werden. “ Und da ist mein Problem: Ich kenne bis jetzt nur Python 3 und weiß nicht, wie genau ich die Packetnamen anpassen muss. Egal wo ich nachschlage, es heißt immer nur sinngemäß, die Bibliothek ist für Python 3 noch nicht vorhanden. Bis jetzt habe ich auch noch kein Beispiel für die Nutzung des PCA 9685 mit Python 3 gefunden.
    Viele Grüße
    Achim

    Antworten
    • Meinst du die Python (Dev) Tools, die du per apt-get installierst? Die gibt es in jedem Fall für Python3. Bei dem pip(3) Paket bin ich nicht sicher, dachte aber dass es verfügbar wäre (Adafruit).

      Antworten
  9. Hallo Felix,
    danke für die Antwort. Ehrlich gesagt, ich weiß nicht ob es um die Dev Tools geht oder um das pip(3) Packet. Ich versuche mein Problem mal so zu erklären: Ich habe die Bibliothek unter
    /home/pi/servo/Adafruit_Python_PCA9685 installiert. Wenn ich dort unter examples
    sudo python simpletest.py ausführe läuft es, wenn ich
    sudo python3 simpletest.py versuche, geht es eben nicht. Meine Frage ist, was genau muss ich in simplest.py oder anderswo ändern?

    Danke, viele Grüße
    Achim

    Antworten
      • Hallo Felix,
        super, genau das war’s!
        Jetzt läuft es mit Python3 vom Terminal aus wie auch aus der IDLE für Python 3.
        Ganz herzlichen Dank für die Unterstützung,
        Achim

  10. Hi Felix,

    I encounter some problem with this system when multiple servos were used.

    Its all fine when:
    1- Moving the servos individually
    2- Moved the servos simultaneously but each servo has different pulse length
    eg:
    pwm.set_pwm(0, 0, 120)
    pwm.set_pwm(4, 0, 530)
    pwm.set_pwm(8, 0, 280)
    3- Move the 2 servos from their current pulse length to the other servo pulse length
    eg:
    pwm.set_pwm(0, 0, 120)
    pwm.set_pwm(4, 0, 120)
    pwm.set_pwm(8, 0, 120)

    Its become weird when:
    1- Moved every servos from different current pulse length simultaneously with the same pulse length
    eg:
    pwm.set_pwm(0, 0, 300)
    pwm.set_pwm(4, 0, 300)
    pwm.set_pwm(8, 0, 300)

    What happen are the servos will first move to the desired position then they start to stuttered and move their own like seeking for the correct position.
    This situation can last up-to 1s till 5s until they actually stabilize and reach the desired position.

    Really looking forward if you ever encounter this problem

    Antworten
    • For some pulses/angles, it is normal that the motors stutter. You could try to wait some ms before moving the next motor. Voltage is enough?

      Antworten
  11. Hallo Felix,
    was hältst Du von dem Adafruit 16 Channel Hat
    https://learn.adafruit.com/adafruit-16-channel-pwm-servo-hat-for-raspberry-pi?view=all
    im Vergleich zu der einfachen PCA9685-Platine, die Du hier beschrieben hast?
    Adafruit schreibt, dass der Raspberry Pi Probleme hätte, exakte Pulse zu generieren und man die Arbeit besser diesem Hat überlassen sollte.
    Wie siehst Du das? Gibt es mit der einfachen PCA9685-Platine Probleme bei der Feinjustierung eines Servos?

    Antworten
    • Ich hab den Adafruit Hat nicht getestet, aber vermute, dass er einen ähnlichen IC verwendet. Das mit dem Zucken am Pi stimmt – habe ich auch erlebt. Es gibt manche Pulslängen, bei denen die Servos „rattern“. Ob es am Servo oder an der Frequenz liegt, habe ich nicht nachgemessen.

      Antworten
      • Ja, das Adafruit Hat benutzt auch den PCA9685, hat aber noch einen eigenen Taktgeber.
        Das Rattern erlebe ich bei meinem Lynxmotion Roboterarm AL5D auch, obwohl er über eine eigene, spezialisierte Steuerplatine SSC-32 gesteuert wird.
        Lynxmotion schreibt dazu, dass das normal sei, da die Servos beständig nachgesteuert würden.

        Aber mit der Ansteuerung jeder einzelnen Gradzahl des Servos an sich hast Du keine Probleme?

  12. Das Beispiel läuft hervorragend. Ich hab da mal ne Frage
    Kann man die Geschwindigkeit zwischen Min und Max Steuern?

    Antworten
    • Hallo Felix
      ich habe mein Problem so gelöst:

        for i in range(servo_anz):
              servo1_pos=int(servo1_pos+servo1_step)
              pwm.set_pwm(kanal1, 0, servo1_pos) 
              time.sleep(v_zeit)
              
              servo2_pos=int(servo2_pos+servo2_step)
              pwm.set_pwm(kanal2, 0, servo2_pos)
              time.sleep(v_zeit)
      Antworten
  13. Hallo Felix,
    Habe das Modul ordnungsgemäß angeschlossen und deinen simpletest.py installiert und ausgeführt jedoch tut sich nichts, kann es sein das der PCA9685 defekt ist?

    Antworten
  14. Hallo Felix,
    danke für deine ausführliche Beschreibung.
    Es hat funktioniert.Probiere gleich mal mehrere Servos aus.
    Gruß Uli

    Antworten
  15. Hallo
    wir haben ein „kleines“ Schulprojekt am Laufen und benötigen ein wenig Hilfe.
    Das Skript funktioniert einwandfrei unser Problem ist es aber das der Motor weiter läuft bzw. sich weiter bewegt obwohl das Skript beendet wurde. Unsere Frage ist wie können wir diese Problem beheben? Wir haben schon versucht mit dem stop() befehl am Ende des Skriptes zu lösen aber hatten kein Erfolg.
    Zusätzlich haben wir die Aufgabe die Motoren mittels Pfeiltasten zu steuern. Gibt es da eine Möglichkeit dies umzusetzen?

    Antworten
  16. Pingback: Building a hexapod robot - more building and a lot to learn - Stricker Consulting

  17. Hallo Felix,

    danke für diese coole Seite.
    Ich habe ein Projekt bei dem ich auch Motoren einsetzen möchte und zwar will ich eine Art Schublade aus einem Gehäuse ausfahren lassen und anschließend aufrichten, ähnlich der Navigationssysteme in einem modernen Audi 😉
    Ich hatte überlegt zeitlich verzögerte Motoren auzusteuern, also erst ein paar, dass die „Schublade“ an sich rausfährt und dann zwei, die das Aufrichten übernehmen. Ich muss dazu sagen, dass ich bisher nur den RaPi an sich habe und noch keine weiteren Komponeten gekauft habe…
    Hast du vielleicht einen guten Tipp, was Komponenten angeht oder einen besseren Vorschlag für die Realisierung? Danke und viele Grüße

    Peter

    Antworten
  18. Hallo,
    Funktioniert einwandfrei, möchte das pythonskript aber von einem C programm aufrufen und ausführen lassen. Die Daten zum steuern der servos sollen vom C Programm übergeben lassen werden.
    Dachte mir das so:
    .
    .
    .
    # include
    .
    (hier steht der C Code)
    .
    Int Wert1;
    Int Wert2;
    Int wert3;
    FILE* file_1 = fopen(„/home/pi simpletest.py – i Configuration.ini“) ;
    Py_Initilize;
    PyRun_SimpleFile(file_1, „/home/pi simpletest.py -i Configuration.ini“);
    PY_Finalize();
    .
    .
    .
    Return;

    (in Kommandozeile)
    gcc Programm. C – o Programm – I/usr/include/python 2. 7 – lpython2. 7

    Problem ist nur er erkennt python. h nicht an und ich weiß nicht wie ich die Werte in das pythonskript übertrage
    Kann da jemand helfen?

    Antworten

Hinterlasse einen Kommentar

Deine Email Adresse wird nicht veröffentlicht.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Blog abonnieren

Abonniere Raspberry Pi Tutorials, um kein Tutorial mehr zu verpassen!