Kampis Elektroecke

Servo ansteuern mittels PCA9685

Raspberry Pi

In diesem Teil des Tutorials möchte ich zeigen, wie mit Hilfe eines PCA9685 PWM Controllers ein Servomotor angesteuert werden kann. Bei einem Servo handelt es sich um einen kleinen Getriebemotor, der mit Hilfe eines Potentiometers, welches mit der Drehachse verbunden ist, seine Drehposition bestimmen und so selbstständig korrigieren kann. Für Servomotoren mit drei Anschlussleitungen gilt in vielen Fällen die folgende Belegung:

  • GND (Braun)
  • Vcc (Rot)
  • Signal (Orange)

Die Ansteuerung des digitalen Servos erfolgt über ein 50 Hz PWM-Signal, wobei die Pulsbreite des Signals die Endposition des Servomotors festlegt.

Das Signal für den Servo wird mit Hilfe eines PCA9685 I2C PWM Controllers von NXP erzeugt. Mit Hilfe dieses Chips kann ein Mikrocontroller (oder in diesem Fall der Raspberry Pi) PWM Signale mit einer Auflösung von 4096 Bit und einer maximalen Frequenz von 12 kHz, bei Verwendung einer externen 50 MHz Taktquelle, erzeugen. Der Controller verfügt über 16 unabhängige PWM-Ausgänge und bringt von sich aus einen internen 25 MHz Oszillator mit. Über einen Vorteiler kann die Ausgangsfrequenz der PWM eingestellt werden.

Vor der ersten Verwendung sollte der Baustein zurückgesetzt werden um einen definierten Ausgangszustand herzustellen. Über die Software kann ein Reset erzeugt werden, indem das Datenbyte 0x06 an die Adresse 0x00 gesendet wird.

Bus = smbus.SMBus(1)
Bus.write_byte(0x00, 0x06)

Nachdem der Baustein zurückgesetzt worden ist, muss dieser neu konfiguriert werden. Die Konfiguration erfolgt über zwei Konfigurationsregister die über die Adresse 0x00 und 0x01 angesprochen werden, und über das Vorteilerregister, welches über die Adresse 0xFE angesprochen wird, erfolgt. Der Vorteiler für das Ausgangssignal kann nur gesetzt werden, solange das SLEEP-Bit im MODE1-Register gesetzt und der Oszillator deaktiviert ist. Da das SLEEP-Bit nach einem Reset automatisch gesetzt ist, soll als erstes der Vorteiler eingestellt werden. Es gilt:

Prescaler = \frac{f_{osc}}{4096 \cdot f_{out}} - 1

Für eine Frequenz von 50 Hz ergibt sich somit ein Vorteiler von 121. Dieser Wert wird nun in das PRE_SCALE-Register geschrieben:

Bus.write_byte_data(ADDRESS, 0xFE, 121)

Im nächsten Schritt werden die Konfigurationsregister beschrieben, wobei die Funktionen der Bitfelder dem Datenblatt des Controllers entnommen werden können:

Wenn kein externer Oszillator genutzt oder die Ausgangstreiber des Controllers anders konfiguriert werden sollen ist der Konfigurationsaufwand überschaubar. Es muss lediglich das SLEEP-Bit gelöscht werden um den Oszillator zu aktivieren. Dazu lese ich das Konfigurationsbyte aus dem MODE1-Register aus, lösche das Bit und übertrage das neue Konfigurationsbyte zurück auf den Controller:

Config = Bus.read_byte_data(ADDRESS, 0x00)
Config &= ~(0x01 << 0x04)
Bus.write_byte_data(ADDRESS, 0x00, Config)
time.sleep(1)

Nachdem das SLEEP-Bit gelöscht wurde, benötigt der Oszillator mindestens 500 µs bevor er stabil arbeitet.

Jetzt kann auch schon die PWM erzeugt werden. Jeder PWM-Kanal wird über vier Register konfiguriert, die in zwei Paare unterteilt werden. Das ON-Registerpaar bestimmt die Zeit, die der Controller vom Anfang einer jeden Periode an wartet, bevor er das Signal einschaltet. Das OFF-Registerpaar bestimmt die Zeit, die der Controller vom Anfang einer jeden Periode an wartet, bevor er das Signal ausschaltet. 

Um z. B. eine PWM mit einem Tastgrad von 20% zu erzeugen, muss der Wert 819 in das OFF-Register des PWM-Kanals geschrieben werden. 

OFF = \frac{4096}{100}\cdot Duty

Dieser Wert muss mit dem Wert des ON-Registers addiert werden. Da die Einschaltverzögerung in diesem Beispiel nicht wichtig ist, soll das ON-Register auf Null gesetzt werden. Beide Werte werden nun auf den Controller übertragen. Die Adresse der entsprechenden Register ergibt sich aus dem Wert des PWM-Kanals inkl. eines Offsets, der die unteren und oberen Bytes der ON– und OFF-Register adressiert:

Register Adresse
ON – Low Byte \left ( Channel \cdot 4 \right ) + 6
ON – High Byte \left ( Channel \cdot 4 \right ) + 7
OFF – Low Byte \left ( Channel \cdot 4 \right ) + 8
OFF – High Byte \left ( Channel \cdot 4 \right ) + 9

Für den PWM-Kanal 0 müssen also die folgende Werte übertragen werden:

Bus.write_byte_data(ADDRESS, 6, 0x00)
Bus.write_byte_data(ADDRESS, 7, 0x00)
Bus.write_byte_data(ADDRESS, 8, (819 & 0xFF))
Bus.write_byte_data(ADDRESS, 9, ((819 >> 0x08) & 0xFF))

Hinweis:

Es kann natürlich auch das AI-Bit im MODE1-Register gesetzt werden, sodass die Register alle nacheinander adressiert werden können. Leider funktioniert dies in Zusammenarbeit mit dem write_block_data-Befehl des SMBus-Moduls nicht richtig. Daher habe ich es bei der „langsameren“ Methode belassen und die Registeradressen bei jeder Übertragung mitgeschickt.


Und schon gibt der Controller eine PWM mit einem Tastgrad von 20% aus:

Für einen Servomotor muss sich der Tastgrad im Bereich zwischen 1 und 2 ms, also zwischen 5 und 10% bewegen, wobei ein Tastgrad von 1,5 ms bzw. 7,5% der Mittelstellung des Servos entspricht. Aus diesen Werten kann nun eine Funktion entworfen werden die einen gegebenen Winkel in den entsprechenden Tastgrad umrechnet, wobei sich der Servo um ±45° um den Nullpunkt drehen soll.

MAX_ANGLE = 45.0

def AngleToPWM(Angle):
	if((Angle > MAX_ANGLE) or (Angle < -MAX_ANGLE)):
		print("[ERROR] Invalid servo angle!")
		Angle = 0

	return 7.5 - (Angle * 0.055)

Die Funktion muss jetzt noch mit ein paar Werten gefüttert werden. Dies kann z. B. über die Kommandozeile erfolgen:

import time
import smbus

ADDRESS = 0x40

MAX_ANGLE = 45.0

def AngleToPWM(Angle):
	if((Angle > MAX_ANGLE) or (Angle < -MAX_ANGLE)):
		print("[ERROR] Invalid servo angle!")
		Angle = 0

	return 7.5 - (Angle * 0.055)

Bus = smbus.SMBus(1)
Bus.write_byte(0x00, 0x06)
Bus.write_byte_data(ADDRESS, 0xFE, 121)
Config = Bus.read_byte_data(ADDRESS, 0x00)
Config &= ~(0x01 << 0x04)
Bus.write_byte_data(ADDRESS, 0x00, Config)
time.sleep(1)

print("[INFO] Configuration: {}".format(Bus.read_i2c_block_data(ADDRESS, 0x00, 0x02)))
print("[INFO] Prescaler: {}".format(Bus.read_byte_data(ADDRESS, 0xFE)))

while(True):
	Channel = int(input("[INPUT] Output channel (0 - 15): "))
	Angle = float(input("[INPUT] Duty cycle (-{} - {}): ".format(MAX_ANGLE, MAX_ANGLE)))

	try:
		if((Channel > 15) or (Angle > MAX_ANGLE) or (Angle < (-MAX_ANGLE))):
			print("[ERROR] Wrong input!")
			continue

		Angle = int(4096.0 / 100.0 * AngleToPWM(Angle))

		Bus.write_byte_data(ADDRESS, (Channel * 4) + 0x06, 0x00)
		Bus.write_byte_data(ADDRESS, (Channel * 4) + 0x07, 0x00)
		Bus.write_byte_data(ADDRESS, (Channel * 4) + 0x08, (Angle & 0xFF))
		Bus.write_byte_data(ADDRESS, (Channel * 4) + 0x09, ((Angle >> 0x08) & 0xFF))

	except Exception as e:
		print("[ERROR] Error: {}".format(e))

Das fertige Python-Skript steht in meinem GitHub-Repository zum Download bereit.

→ Zurück

84 Kommentare

  1. Hey Daniel
    Inzwischen gibt es die Version RPi.GPIO 0.5.2a, die kann auch Software-PWM.
    Hab mir gerade mal eine Demo mit 8 LEDs geschrieben, die ändern ihre Helligkeit
    der Reihe nach kontinuierlich, hier der Script:
    PythonPWM.py.txt
    Aber wie ich dich kenne biste auch schon damit am Arbeiten…
    Gruß Fritz

    1. Hallo Fritz,

      dank dir für den Hinweis :)
      Hab den Artikel gestern schon dem entsprechend angepasst, weil mir das bereits letzte Woche eingefallen ist. ;)
      Aber das LED Programm ist nett.
      Denke der ein oder andere wird sich das gerne anschauen wollen.
      Danke fürs hochladen!

      Gruß
      Daniel

  2. Hallo Daniel,
    habe mir gerade Dein Servo.py direkt in Python kopiert, bekomme aber beim Starten diesen Sytax Error Error_jpg.
    Habe ich falsch kopiert oder fehlt bei mir die Importdatei „os“?
    Die „RPi.GPIO-0.5.2a“ habe ich installiert.
    Gruß Fritz

    1. Hallo Fritz,

      uups ist mir da jetzt ein Fehler unterlaufen?
      Probier es mal bitte mit dem Modul „os“ und ansonsten kannst du noch

      print str(Schritte) + “ Schritte nach Rechts“

      probieren.

      Gruß
      Daniel

      1. Danke für die schnelle Antwort,
        aber weder Modul „os“
        hier ist „os“ als Fehler gezeichnet
        noch
        print str(Schritte) + ” Schritte nach Rechts”
        hier ist dann „str“ die Fehlerursache.
        Es eilt nicht

        Gruß Fritz

        1. Hallo Fritz,

          ich kann da keinen Fehler sehen.
          Ich verwende das selbe Programm und bei mir läuft es.
          Hast du es vielleicht mit Version 3 von Idle/Python laufen lassen?
          Da hat „print“ eine andere Syntax:

          print(Schritte, „Schritte nach Links“)

          Probier das mal bitte so.

          Gruß
          Daniel

          1. Hallo Daniel,
            da ist auch kein Fehler, nur der Python 3.2.3 versteht die alte Sprache nicht. Der Printbefehl muss in Klammern, da hast Du recht.
            Aber auch der Input-Befehl klappt mit raw_input nicht sondern einfach nur input.
            Ich habe den Script an python 3.2.3 angepasst und für die bequemen hier reingestellt und hoffe du bist damit einverstanden.
            Gruß Fritz

          2. Hallo Fritz,

            ja bei Python 3 haben sie einige Befehle leicht geändert (also die Syntax).
            Davon ist offenbar auch der „raw“ Befehl betroffen.
            Klar kein Problem wenn du es anpasst und veröffentlichst :). Ich hoffe es funktioniert nun einwandfrei!

            Gruß
            Daniel

  3. Danke für den Beitrag, habe ich jetzt mal versucht nach zu machen.

    Mein Aufbau: Servo mit +/- an einem Labornetzteil angeschlossen, Steuerleitung an den GPIO und am Ende noch Servo und RPi Masse verbunden… soweit korrekt?

    Wenn ich jetzt das Programm teste, zuckt der Servo höchstens mal ganz kurz in eine Richtung oder brummt kurz vor sich hin (nicht dieses laute „Hilfe ich bin am Anschlag“-Brummen, ehr ein leises „da ist ein Signal, aber ich ich weiß nix damit anzufangen“-Brummen).

    Jetzt hab ich mit mehrere Fehlerquellen überlegt, mangels Erfahrung mit Servos, weiß ich aber nicht weiter. Steuerspannung aus dem GPIO zu gering? Timings zu ungenau, ist ja kein Echtzeitbetriebssystem?

    Servo ist ein älterer Modelbauservo von Conrad, der ES-035

    Gruß
    Carsten

      1. Danke für deine Antwort.

        Denke schon, 2A sollten locker reichen und es würde auch anzeigen, wenn die Grenze erreicht ist.

          1. Nein, leider nicht, den gibt es bei Conrad nicht mehr und im Netz finde ich nix… ich meine aber es waren die Stellzeiten bei 5 und 6V angegeben… meinst du der Pegel ist zu niedrig? Wie gesagt, ich habe leider von Servos keine Ahnung, wollte die vor ein paar Jahren mal zusammen mit einem ATMega32 zusammen verwenden, aber irgendwie ist das Projekt eingeschlafen… wollte die für den RPi reaktivieren, damit sie nicht doof rumliegen… vielleicht gucke ich morgen bei Conrad mal nach anderen Servos…

          2. Mehr fällt mir dazu im Moment leider auch nicht ein.
            Wenn du kannst probier mal einen anderen.

          3. Danke dir, ich werde mir morgen mal den Servo kaufen, den du benutzt hast und das damit testen, sollte dann ja eigentlich hinhauen… ich werde berichten.

            Gruß
            Carsten

          4. Huhu,

            hier die Rückmeldung :-)
            Mit dem neuen Servo läuft es… auch wenn ich das Drehverhalten des Servos noch nicht ganz nachvollziehen kann…

          5. Hey,

            klasse das es nun klappt.
            Was genau meinst du mit „nicht nachvollziehen“?

            Gruß
            Daniel

          6. Jetzt hab ich mir vorgenommen ein Video davon zu machen, aber mir fehlt leider die Zeit, deshalb antworte ich erstmal und hoffentlich verständlich…

            Also Programm wird gestartet:

            Ich drücke „m“ für die Mittelstellung und der Servo fährt in die Mitte, so weit so gut… bei r 1 fährt er ca 15° nach rechts… bei l 1 ca 15° nach links… will ich ihn dann in die Mittelposition fahren dreht er nach rechts bis zum Anschlag, das gleiche bei allen anderen Eingaben… ich hoffe ich schaffe es in den nächsten Tagen mal ein Video zu machen, dann wird es noch klarer…

          7. Hi,
            Ich habe genau das gleiche problem wie Carsten.
            egal was ich eingebe, der servo dreht nur nach rechts. ich habe an dem programm nichts verändert (außer die gpio belegung). Es ändert sich nur die zeit, wie lange nach rechts gedreht wird, je nach dem wie viele schritte ich eingebe.

          8. Hey,

            da es sich um eine Software PWM handelt kann es sein, dass sich der Servo deswegen nicht bewegt.
            Eventuell stimmen die Tastverhältnisse nicht.
            Du kannst mal dieses Modul verwendenn:

            https://pythonhosted.org/RPIO/pwm_py.html

            Da wird per Hardware eine PWM erzeugt….die ist deutlich genauer. Damit sollten die Probleme nicht mehr auftreten.
            Andernfalls ist ein Servocontroller auch keine schlechte Wahl.
            Eine Software PWM über einen Rechner zu generieren ist leider nicht ganz so toll :(

            Gruß
            Daniel

  4. Hallo,

    danke für die ausführlichen Beitrag!

    Mein Servo: Servo – Large ROB-09064 (Spezifikation http://www.spikenzielabs.com/Catalog/index.php?main_page=product_info&products_id=78)

    Meine Stromquelle: 6×1,5 V in Reihe geschaltet, gemessen mit Spannungsprüfer 4,8 V

    Ich habe RPi.GPIO 0.5.3a installiert.

    Ich hatte versucht über die GPIO 18 versucht die eingebaute Pulse Width Modulation zu verwenden. Mein Schaltkreis war der folgende: http://learn.adafruit.com/adafruits-raspberry-pi-lesson-8-using-a-servo-motor/hardware

    Das hat jedoch nur bedingt geklappt, da der Servo sich nur einmal in eine Richtung gedreht hat und dann nur noch brummte.

    Dann habe ich deinen Code mit dem softwaremäßigen PWM-Signal versucht. Hier klappt es beispielsweise zweimal mit l + 30 und danach r + 30. Danach hört man bei einem weiteren Befehl nur ein kurzes Geräusch, jedoch kein Brummen mehr.

    Wäre super von dir, wenn du einen Tipp hättest, der mir hilft, dass ich den Servo kontrolliert steuern kann!

    Vielen Dank,

    Stefan

    1. Hey,

      ich habe gemerkt, dass du teilweise die PWM ein bisschen verändern musst damit es funktioniert.
      Bei mir war das Problem, dass sich der Servo bei gleicher Schrittweite unterschiedlich weit nach links und rechts gedreht hat.
      Spiel mal etwas an diesen Zeilen hier rum:

      Servo.start(10)

      Damit kannst du die PWM „justieren“. Eventuell löst das bereits dein Problem.

      Gruß
      Daniel

  5. Hallo,

    um die Funktion des PWM auszuprobieren habe ich den Quellcode modifiziert um einfach eine LED für 10 Sekunden zum blinken zu bringen.


    import RPi.GPIO as GPIO
    import time
    import os

    # Pin 2 als Ausgang deklarieren
    # GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(2, GPIO.OUT)

    while True:

    # PWM mit 0.5Hz an GPIO 2 starten
    Servo = GPIO.PWM(2, 0.5)

    # Richtungseingabe
    Eingabe = raw_input("Bitte treffen Sie Ihre Wahl: ")

    # Richtung "Rechts"
    if(Eingabe == "r"):

    # Tastverhaeltnis
    TV = float(raw_input("Tastverhaeltnis: "))
    print TV, "% Tastverhaeltnis"

    # PWM mit Dutycycle generieren
    Servo.start(TV)
    time.sleep (10)

    # PWM stoppen
    Servo.stop()

    # Programm beenden
    elif(Eingabe == "q"):
    print "Programm wird beendet......"
    os._exit(1)
    Servo.stop()
    GPIO.cleanup()

    # Ungueltige Eingabe
    else:
    print "Ungueltige Eingabe!"

    Beim ersten Durchlauf funktioniert das ganze auch wie gewollt.
    Die LED blinkt mit der eingestellten Frequenz von in dem Fall 0,5Hz.
    Bei jedem weiteren Durchlauf scheint Frequenz der PWM deutlich höher zu sein.
    Man kann kein Blinken mehr erkennen, die LED wird je nach Tastverhältnis einfach nur dunkler.
    Habe ich da einen Fehler gemacht oder muß man da einen Trick anwenden?

    Ich habe einen 512MB Pi.

    Gruß,
    Axel

  6. Klappt leider nicht.
    Auch nicht, wenn ich es am Ende jeden Durchlaufs mit GPIO.cleanup() und anschließendem Neustart der PWM versuche.
    Scheinbar funktioniert die Festlegung der PWM-Frequenz nur beim ersten Durchlauf.

    1. Hey,
      setz die Zeile

      Servo = GPIO.PWM(2, 0.5)

      mal vor die while-Schleife. Das ist die Instanziierung der PWM und die braucht nur 1x gemacht werden.
      Vielleicht ist das ja der Fehler.

      Gruß
      Daniel

      1. Nein, das ist es nicht.
        Habs gerade ausprobiert.

        Einmal hats inzwischen in zwei Durchläufen funktioniert.
        Beim nächsten Programmstart wieder nur beim ersten.
        Wird wohl nicht am Skript liegen.

  7. Wenn ich einen Befehl ausführe, zb. „r“ und „45“ (unter python 2.7) wird dieser ausgeführt und das System bleibt stehen (und fährt runter). Die Netzwerkverbindung wird unterbrochen. Der Code ist einen Copie aus Deiner Seite, ohne Änderungen. Das RPi.GPIO Paket ist die Version 0.5.3a.
    Hab nur ich das Problem?
    Wie bekomme ich es weg?

      1. ich bin mir ziemlich sicher, dass der Servo richtig angeschlossen ist. Der Servo bewegt sich ja, aber nur 1mal. Wenn ich CTRL-C (mehrfach) drücke, komme ich oft zur Befehlszeile zurück.
        Zugegebenermaßen, testweise, hängt er direkt am GPIO, also ohne eigene Stromversorgung.

        1. Hey,

          da musst du vorsichtig sein!
          Im Servo ist ein Motor und je nachdem wie viel Anlaufstrom der zieht, kannst du damit den Spannungsregler auf dem Board in die Knie zwingen (was bei dir offensichtlich der Fall ist).
          Versorg den Servo mal extern mit Spannung, verbinde nur die GND miteinander und den Signalpin schließt du an den GPIO an….dann sollte es funktionieren :)

          Gruß
          Daniel

  8. Hallo Daniel,

    ich wollte grad mal dieser Anweisung folgen, bekomme aber beim Ausführen von
    „sudo python setup.ph install“ die Fehlermeldung „source/py_gpio.c:23:20: fatal error: Python.h: Datei oder Verzeichnis nicht gefunden“

    eine Idee was ich falsch mache???

    Danke und Gruß

    Chrissy

          1. so, gecheckt… war natürlich nicht installiert…
            Warum bekomme ich eigentlich beim Ausführen von: „import RPi.GPIO as GPIO“ die Antwort: „-bash: import: Kommando nicht gefunden.“ ??? Kannst Du mir da weiterhelfen?

            Danke
            Chrissy

          2. PABMAC…sorry
            kann es sein, dass mit der initialisierung im skipt „Servo.py“ was nicht stimmt? Ich kenn mich NULL mit Python aus!!! wenn ich das skript ausführe und zwei oder drei schrittweiten eingebe, macht der Servo nicht mehr so richtig was er soll. Erst wenn ich Python beende und von vorn beginne klappts ermal wieder… bis er dann wieder statt link rechts herrum dreht und die mittenstellung auch nicht findet… Hmm
            Das skript ist von dir aus dem link oben.

            Gruß

            Chrissy

  9. Hallo,

    auch ich bleibe als Raspberryneuling an der Stelle mit “import RPi.GPIO as GPIO” die Antwort: “-bash: import: Kommando nicht gefunden.” hängen.

    Das Tutorial verstehe ich so, dass man “import RPi.GPIO as GPIO” direkt in die konsole eingibt. aber da fehlt doch noch irgendwas?!

    Vielen dank schonmal bis dahin für das Super tutorial LEDs ein und ausschalten hat perfekt funktioniert. Nur mit dem lighttpd kämpfe ich noch ein wenig :-)

    Gruß
    Bastelfreund

          1. so wie es im Tutorial steht :-)
            Ich befinde mich in der Konsole, habe folgenden Schritt ausgeführt

            „Danach könnt ihr die Überbleibsel löschen:

            $ cd .. $ sudo rm -rf RPi.GPIO-0.5.2a/
            $ rm RPi.GPIO-0.5.2a.tar.gz“

            Und anschließend ebenfalls in der Konsole

            „import RPi.GPIO as GPIO“

            eingegeben. Mir kommt es aber irgendwie so vor als wenn da eine wichtige, für einen Anfänger wie mich, Information Fehlt. Wie führe ich „import RPi.GPIO as GPIO“ korrekt aus? Also mit was?

            gruß
            Bastelfreund

          2. Hey,

            wenn du Python Befehle in der Konsole aufrufen willst, musst du erst mit dem Konsolenbefehl

            python

            den Python Interpreter starten. Dann kannst du die Befehle in die Konsole eingeben und sie werden ausgeführt.
            Und im Tutorial steht, dass das Modul mit dem Befehl in das SERVOPROGRAMM eingebunden wird :)
            Das ist nicht mehr in der Konsole. Du hast dein Python Programm und jedes Modul was du verwenden willst musst du erst einbinden. Dies geschieht über den Befehl „import“.
            Ich glaube du hast es nur falsch gelesen :)

            Gruß
            Daniel

    1. Freut mich das es nun funktioniert!
      Wenn sich ein Servo nicht richtig bewegen sollte oder nicht komplett dreht (was bedingt durch Timingtoleranzen etc. passieren kann), musst du bisschen an dem Zahlenwert in dem Befehl

      Servo.start(10)

      rumschrauben (musst du dann wahrscheinlich bei allen unterschiedlich machen).

      Gruß
      Daniel

  10. Hi Daniel,
    super Tutorial ☺
    Klasse dass du es hochgeladen hast.
    Grüße Dominik
    PS: User hatten tw. Probleme bei der Umsetzung, bei mir lag es am digitalen Servo, die mag der Pi wohl nicht…

    1. Hey Dominik,

      freut mich das es dir weiter geholfen hat.
      Ich hab mich leider noch nie wirklich mit digitalen Servos beschäftigt, von daher kann ich dir leider nicht genau sagen woran es liegt.
      Laut Internet sind die genau so anzusteuern wie analoge, allerdings kannst du mal probieren ob du evtl. die PWM Frequenz erhöhen musst.

      Gruß
      Daniel

  11. Hey,
    Vielen dank für das Tutorial!
    Aber ich bekomme immer die Fehlermeldung „nö Access to /dev/mem. Tray Running as Root!
    Bei line gpio.setup(26, gpio.out)
    Mit freundlichen Grüßen
    Lars

    1. Hey,

      du musst das Programm als Benutzer „root“ ausführen, da du für den Zugriff auf die Hardware (GPIO, etc.) Root-Rechte benötigst.

      Gru0
      Daniel

      1. Danke, für die schnelle Antwort, aber wenn ich mich als root anmelden will, frag er nach einem Passwort, das kenne ich aber nicht. Kennst du das Standardpasswort für das System wheezy? Und ist dein Skript auch geeignet, 2 Servos anzusteuern?
        Tut mir leid, ich kenne mich echt gar nicht aus. Aber muss dringend 2 Servos von meinem raspberry pi steuern.

        Gruß
        Lars

        1. Hey,

          du musst das Passwort erst anlegen.
          Mittels

          $ sudo su

          kannst du dich als root anmelden und dann mittels

          $ passwd

          das Passwort festlegen.
          Das Programm kannst du auch für zwei Servos verwenden. Du musst dann nur die entsprechenden Befehle doppelt verwenden :)

          Gruß
          Daniel

          1. Danke.
            Das ging schonmal Super, doch leider meldet er mich dann nicht auch in der Shell als root an. Dort bleibt die gleiche Fehlermeldung. Wie kann ich auch in der Shell root sein?
            Vielen Dank für deine Geduld!

          2. Hey, also root geht jetzt:)
            Aber er zeigt mir immer einen Syntax Error an. Und zwar die 2 bei Python 3.2.3 ganz oben. Woran liegt das?

  12. wenn ich mir den code anschaue, dann verstehe ich ihn nicht so recht.
    eventuell gibt es unterschiedliche servos. aber die ich kenne, stellen den Servo proportional zur Länge der Hi Flanke. Das über ein sleep in der Zeit zu steuern finde ich seltsam. Oder anders gesagt, dass hat dann für mich nichts mehr mit PWM zu tun. Dort müsste ich eine Frequenz angeben, die den kompletten Bereich des Servos abdeckt und dann in % angeben, wieviel ich davon will. Oder aber ich mache es mit Hi Low Flanken selber und sleep. Nur dafür ist Linux etwas zu lahm.
    alles andere geht vermutlich auch irgendwie, aber nicht zuverlässig.

    1. Hallo,

      den Servo den ich verwendet habe, bewegt sich mit jedem Puls mit einer bestimmten Länge in eine bestimmte Richtung.
      Was das Programm also macht, ist den Puls zu erzeugen und je nach Anzahl der Schritte dann eine Schleife zu durchlaufen, die die Anzahl der Pulse umsetzt, indem sie das Programm für eine gewisse Zeit pausiert. In der Zeit werden dann weitere Pulse erzeugt und der Servo bewegt sich bei jedem Puls einen Schritt weiter.
      Es geht wahrscheinlich auch schöner, nur diese Lösung erfüllt den Zweck voll und ganz und ist recht einfach umzusetzen.

      Gruß
      Daniel

  13. Hi,

    ich habe deine Anleitung mal soweit befolgt, habe jedoch zur stromversorgung ein USB-Kabel umgelötet und an mein Handyladegerät angesteckt. Mein Servo ist ein Modelcraft rs2, das Skript läuft so halb jedoch lenkt der Servo nur nach links, egal was ich ihm sage. Außer wenn ich auf m stelle, dann geht er ganz nach links, dann dauerts und dann geht er grob in Mittelstellung.
    Muss ich an den Pulsbreiten was ändern?

    Yannic

    1. Hey Yannic,

      das kann gut sein, dass du die Pulsbreite (oder auch die Frequenz!) anpassen musst.
      Spiel einfach mal mit den Werten, eventuell wird es dann besser.

      Gruß
      Daniel

      1. Hi,

        habe die Pulsbreite aus dem Datenblatt des Servos genommen und umgerechet, trotzdem, hat das ganze Programm gesponnen. Habe jetzt hiermit gearbeitet:

        from RPIO import PWM
        servo = PWM.Servo()

        Hat diese Herangehensweise Nachteile (also cpu Last?)
        Meein Ziel ist es, den PI auf einem Modellauto einzusetzen, dazu muss ich auch noch das PWM-Signal des Fahrtenreglers rekonstruieren, hast du damit eventuell schon Erfahrungen?

        Yannic

  14. Hallo Daniel,
    zuerstmal Danke für Deine SUPER Anleitung. Hat mir sehr geholfen meinen Servo anzusteuern. Ich musste etwas spielen mit Servo.start. Habe diese auf Servo.start(100), Servo.start(7), Servo.start(1) setzen müssen. Mein Problem ist nur, das ich immer eine Schrittweite von 1 eingeben kann. Wenn ich z.b. r 30 mache, macht er nur 1 Schritt nach rechts. Nach Links auch immer nur 1. Mitte findet er nicht immer. Leider stehe ich jetzt etwas auf dem schlauch. Vllt. hast Du mir einen Tipp ?

    Danke und nochmals super Artikel :)

    Andy

    1. Hey Andy,

      das sieht fast so aus, als ob die Pulsbreite nicht stimmt.
      Du musst also noch ein bisschen an den Zahlen von Servo.start() rum schrauben.
      Den Wert 100 halte ich auch für falsch, weil das eine PWM mit einem Duty-Cycle von 100 ist und das ist schon mehr eine konstante Spannung :)

      Gruß
      Daniel

      1. Hallöle,

        nach vielen Tests – keinen schritt weiter.

        Wenn ich dieses Programm nutze, fährt er sauber:
        import RPi.GPIO as GPIO
        import time

        GPIO.setmode(GPIO.BOARD)
        GPIO.setup(26,GPIO.OUT);

        p = GPIO.PWM(26,50)

        p.start(7.5)

        try:
        while True:
        print ‚links‘
        p.ChangeDutyCycle(2.5)
        time.sleep(0.01)
        print ‚rechts‘
        p.ChangeDutyCycle(12.5)
        time.sleep(0.01)
        print ‚Mitte‘
        p.ChangeDutyCycle(7.5)
        time.sleep(1)

        except KeyboardInterrupt:
        p.stop()

        GPIO.cleanup()

        Das mit den PWM Werten hat nichts gebracht. Muss jetzt nur noch testen mit externer Stromversorgung. Der Servero ein HiTec HS-311.

        Stehe ratlos vor dem Pi (:

  15. Hallo, kampi
    Habe schon mehre deiner Projekte und Beispiele nutzen können. Die Seite ist echt klasse! Nun bin ich am Bau eines Roboterarms aus 4 Servos gesteuert über den pi. Bin soweit auch fertig habe nur das ganz große Problem: ist der Pi bereit und ich schalte die Servos an, dann fahren diese in alle möglichen Richtungen. Das seltsame ist nach paaR mal probieren(Servos strom an/aus) sind diese plötzlich ruhig also fahren nicht mehr auf oder zu und dann läuft auch mein programm .. Ales über Python ähnlich deinem Beispiel .. Grus

    1. Hallo Jonathan,

      eventuell stimmen die Pulse von der Dauer her nicht.
      Spiel mal etwas an der Pulsdauer, dann sollte es besser werden.
      Wenn du ein Oszi hast kannst du es natürlich auch damit machen.
      Wenn die Pulse für die Servos zu lang oder zu kurz sind verhalten die sich teilweise echt merkwürdig.

      Gruß
      Daniel

  16. Hi

    Gutes Programm, hab aber eine Frage:
    Geht das auch, z.Bsp. wenn ich einen Taster der an den GPIO angeschlosen ist drücke und nicht eine Taste auf der Tastatur ?

    Danke Jan

  17. Hey,
    Vielen dank für das Tutorial! Hat mir sehr geholfen.
    Mein Servo : HS-785HB 3.5 Rotations https://www.servocity.com/html/hs-785hb_3_5_rotations.html#.VUC_diHtlBf
    Mein Schaltkreis war der folgende: http://razzpisampler.oreilly.com/ch05.html#FIG7.16.
    Also Programm wird gestartet , bei r 15 fährt er ca 15° nach rechts… bei l 1 ca 15° nach links und fast gleich bei andere Werte … will ich ihn dann in die Mittelposition fahren dreht er nach rechts bis zum Anschlag.
    Ich habe versucht den Dutycycle der PWM zu verändern aber hat irgendwie gedreht und Brummen und könnte nicht das Modul per Hardware eine PWM verwenden.
    Mein Servomotor muss eigentlich 110° nach rechts umdrehen und dann dreht züruck in der Mitte und wieder 110° nach links.
    Wäre super von dir, wenn du einen Tipp hättest, der mir hilft, dass ich den Servo kontrollieren kann!
    Vielen Dank,

    Doris

  18. Hallo vielen Dank für deine super Beschreibung.
    Ich hab nur ein paar Probleme…
    Ich benutze folgenden Servo http://www.makeblock.cc/meds15-servo-motor/

    und irgendwas passt da überhaupt nicht. Der Servo fährt die ganze Zeit hin und her, er bleibt überhaupt nicht stehen und wenn er mal annähernd auf einer Position bleibt zittert er total.
    Ich hoffe du kannst mir weiterhelfen.

    Gruß Jan

  19. Hi Daniel,
    im dritten Eintrag von Fritz verweist dieser auf die Steuerung der Servos mit HTML. Ich bin gerade wieder am Basteln damit und musste leider feststellen, das der Link nicht mehr funktioniert :-( Hast du vielleicht noch den Inhalt daraus? Es er realisierte das mit PHP und vier einfachen Dateien, die auf die dein Skrip in Phyton direkt ansprachen. Blöd das ich mir den Inhalt nicht Kopiert habe…
    Danke und Grüße
    Dominik

    1. Hallo Dominik,

      nein, ich habe das leider auch nicht mehr.
      Aber im Grunde funktioniert das (wahrscheinlich) so, dass er mit PHP eine Datei erstellt wo dann z.B. die Anzahl der Schritte und die Richtung drin stehen. Ein Python-Programm liest diese Datei aus und setzt es in eine Servobewegung um.
      Ich denke das ist alles :)

      Gruß
      Daniel

  20. Hallo,
    cooler Blog. Habe mir prompt bei Conrad einen Servo erstanden und zwar den modelcraft analog servo mc-410 und bekomme den servo auch zum bewegen. leider sehr unkoordiniert da ich vermute das die frequenz/timings nicht passen.

    auf der packung steht 4.8/6V: 0.17sec/60C 0.15s/60C – würde das heissen mit 5v auf dem raspberry liegt das irgendwo dazwischen?

    gibt es einen weg das mit einem script herauszufinden?

    danke & gruss jens

    1. Hallo Jens,

      die 4,8 – 6V sind nur die Betriebsspannung. Der Signalpegel beträgt typischerweise 5V.
      Wenn der Servo sich unkontrolliert bewegt stimmt das Timing nicht (oder du hast eine nicht verbundene Masse).
      Probier mal diese Lib aus:

      https://pythonhosted.org/RPIO/pwm_py.html

      Die erzeugt die PWM per DMA und damit ist die Genauigkeit etwas höher und ggf. ist das zucken dann weg.

      Gruß
      Daniel

  21. Hallo,

    vielen Dank. Die Seite hat mir schnell und unkompliziert geholfen, den PCA in Betrieb zu nehmen. Ich nutze allerdings zunächst nur die Kommandos i2cget und i2cset auf dem Raspi.
    Später will ich versuchen, mir eine Art simplen Treiber für Codesys zu bauen.

    Freundliche Grüße
    Alexander

Schreibe einen Kommentar

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