Raspi 3 Servos zittern und hoher Strom

  • Hallo Gemeinde,

    habe 6 Servos per GPIO.PWM angeschlossen.

    Wenn ich diese per tkinter starte, zittern sie und erzeugen einen hohen Strom und werden heiss.

    Externe Stromversorgung der Servos über ein Labornetzteil mit 5V.

    Ich habe mal den Code angehangen.

    Ich würde gerne die Servos mit dem PCA9685 betreiben, weiss aber nicht wie.

    Gruss Bernd

  • Moinsen,

    Das erste was ich sehe , ist eine potentieller Fehler, wenn es sich um Modellbausservos handelt. Hier ist die PWM Frequenz nicht 60 sondern nur 50 Hz !

    Normal kann man eine solche Berechnung der Servopostion auch auch eleganter machen, ohne soviel Overhead zu erzeugen. Dazu nutzt man Mapping das man das Tastverhältnis direkt berechnen lässt.

    Für den PCA9685 gibt es verschiedene Bibliotheken, allerdings solltest du dir im klaren sein, dass I²C auf dem RasPi nicht die voll Geschwindigkeit liefern kann. Für sehr schnelle Feinkorrekturen eher der ungeeignet Weg.
    Dann würde ich auch ein Threshold setzen, in dem ich den letzten Servo Winkelwert innerhalb eines Objektes abgespeichert lasse, und vergleichen, ob es wirklich notwendig ist dem GPIO einen neuen Wert zu übergeben. Weil wenn deine Berechnung immer wieder nur zu minimalen Abweichung führt obwohl sich schlußendlich nicht viel geändert hat, ist das eine Erklärung warum die Servos zittern.
    Also hier einen Funktionspuffer schaffen, das der PWM GPIO erst einen neuen Wert bekommt wenn wirklich eine reproduzierbare Änderung am Servohorn gewünscht wird.

    Franky

  • Hallo,


    wenn man deinen gezeigten Code mal auf das reduziert, was tatsächlich funktioniert und `pwm1` in `pwm` umbenennt, dann bleibt das übrig:

    Dann sieht man, dass die Funktion, die die Frequenz setzt gar nicht aufgerufen wird. Kannst du mal bitte ein lauffähiges Beispiel deines Codes posten, dass trotzdem den gleichen Fehler hat? Der gezeigte Code, endet in einem NameError und ist nicht lauffähig.

    Nur zur Sicherheit, alle Komponenten haben die gleiche Masse?


    Grüße

    Dennis

    🎧 The music, if you can call it that, physically assaults anyone dumb enough to listen 🎧

  • Moinsen,

    Ich bin nicht der Fachmann für TKinter, das gleich mal vorneweg.

    Aber wenn du eine eine Möglichkeit hast, mit "Command" einen Befehl ausführen zu lassen, geht das nicht mit einem Übergabeparameter ?

    Da musst du nicht für jedes Servo eine einzelne Unterroutine schreiben , welche sich inhaltlich ohnehin nicht voneinander unterscheiden.

    So könnte man jeden PWM Ausgang und damit Servo als Objekt verwalten und behandeln, so das du innerhalb dieses Servo Objektes nur eine SET Funktion hast die dann jeweils mit dem Übergabeparameter "Winkel" nur dann eine Änderung des PWM Dutys auslöst, wenn wirklich ein signifikante Änderung des Winkels stattgefunden hat.
    Vielleicht hilft es hier schon den Duty auf eine bestimmte Anzahl Nachkommastellen mittels round() abzuschneiden, um den mathematischen Fehler der vielen Nachkommastellen mitzuschlepppen ?

    Franky

  • Hallo,


    in der Annahme, dass alles ordentlich angeschlossen ist, würde ich mal von `RPi` auf `gpiozero` mit Pigpio wechseln. Das verwendet eine andere Methode zur Erzeugung der PWM und liefert stabilere Signale.


    Starte mal mit einem Motor, was macht dieser Code:

    Die Doku dazu:

    15. API - Output Devices — gpiozero 2.0.1 Documentation


    Noch Anmerkungen zu deinem Code, unabhängig vom Problem.

    Die erste Zeile soll darauf hindeuten, welcher Interpreter genutzt wird, falls dieser beim Aufruf nicht angegeben wird. Das wird aber nur erkannt wenn nach dem `#` ein Ausrufezeichen kommt und dann hat da `bash` eigentlich nichts zu suchen. Richtig wäre #!/usr/bin/env python


    Man importiert nicht mit einem Stern. Du holst dir da *alle* Namen in dein Programm. Das sind nicht nur die von `tkinter` sondern auch die die darin importiert werden. Man weis nachher nicht mehr wo was her kommt und es kann zu Namenskollisionen führen.

    `as` ist zum umbennenen da, du nennst `GPIO` in `GPIO` um. richtig wäre from RPi import GPIO

    Man nummeriert keine Namen durch, weil dass dem Leser keinen Mehrwert bietet, da wählt man eher eine passende Datenstruktur, wie eine Liste.

    Auf Modulebene, der Code ohne Einrückungen, darf kein ausführbarer Code stehen, hier werden nur Konstanten, Klassen, Funktionen und der Einstiegspunkt in die `main`-Funktion definiert. Ein Python-Programm startet üblicherweis in der `main`-Funkion. Von dort aus werden weitere Funktionen aufgerufen, Parameter übergeben und Rückgaben entgegen genommen.

    Es ist sehr fehleranfällig für alles 6 mal den gleichen Code zu schreiben, wenn die Logik die selbe ist. Man muss bei einer Änderung genau schauen, das jede Funktion gleich geändert wurde, die Fehlersuche ist aufwendig und als Leser überlegt man nach dem Sinn für soviele Funktionen.

    Funktionen schreibt man in Python klein_mit_unterstrich. Namen wie `d1` sind nichts sagen, besser immer sprechende Namen verwenden. Strings puzzelt man nicht mit '+' zusammen, sondern verwendet `f`-Strings. Es macht keinen Sinn `d1` an `Achse1` zu binden um `Achse1` `print` zu übergeben und `d1` an `ChangeDutyCycle`

    Zwischenstand ungetestet:


    Grüße

    Dennis

    🎧 The music, if you can call it that, physically assaults anyone dumb enough to listen 🎧

  • Moinsen,

    Dennis89 ich möchte deinen Programmierkünsten nicht widersprechen. Allerdings sehe ich hier eine potentiellen Fehler. Auch wenn die PWM Taktfrequenz für einfache Servo Antriebe nur 50 Hz beträgt, das PI bis zum / einschließlich Modell 4 Verfügt nur über 2 HW PWM Kanäle.
    Damit muss der ganze Murks für die rechtlichen 4 Servos mit echter CPU Power erzeugt werden.
    Wie ich schon sagte, ich kenne mich in den TK Routinen nicht aus, aber ich nehme an, das es ein Loop ist, der bei jedem Durchlauf den PWM Wert unabhängig ob eine Änderung durch die GUI stattfindet oder nicht als neuer Duty_Value an den PWM Pin gesendet wird ?
    So wie ich den Code aus der verlinkten Doku zu GPIOZERO lese wird das Duty Ergebnis in einem Bereich zwischen -1 und 1 abgehandelt und dabei eine Genauigkeit ( Nachkommastellen < 14 ) verwendet.
    Wenn man sich schon einmal etwas mit Modellbau beschäftigt hat, könnte man zur Erkenntnis kommen, das dieser Bereich -1 bis +1 mehr als 2048 Zwischenschritte umfasst. Die meisten einfachen Servos mit einem analogen Poti als Winkelgeber können jedoch nur 2048 Schritte machen, um den Stellbereich 180 Grad abzudecken. Einige Digitalservos können mehr, liegen dann aber in einer Preisklasse die deutlich über 100€ liegen. Solange wir vom TO bernhardjunk nicht erfahren was für Servos er einsetzt, bzw. ob diese Servos eine Haltelast erbringen müssen ( was ich aber bei den Namensbezeichnern annehmen würde ) wenig sinnvoll die Servos mit so ausgefuchsten und genau berechneten Tastverhältniswerten zu ärgern.
    Normal sollte man die Programmierung dann nicht mit diesen Verhältniswerten -1 bis +1 für 180 Grad unnötig genau machen, sondern schon bei der Initiierung als eigenständiges Objekt darauf achten, das wenn von der GUI absolute Winkelwerte übergeben werden, diese dann auch mit einer Schrittweite versehen werden, so das man wirklich den Vorgang des Neubeschreibens des Duty_Values nur dann ausführen lässt, wenn sich der aktuelle von der GUI gelieferte Wert über das Minimale Schrittmaß hinaus geändert hat.

    Hier wäre es, wie vom TO gesagt oder vorgeschlagen, sinnvoller sich mit diesem Code und dem PCA9685 zu beschäftigen. Zumal man hier nicht diesen Umfang von GPIOZERO mitschleppt, und auch noch einfacher eine Mindestschrittweite einfügen kann. So dass das Servo mit einem Konstanten Duty während der nicht aktiven Bewegunsgphasen sich von alleine um den Positionserhalt kümmern kann. Denn solange ein konstanter PWM Duty anliegt, ist das Servo eigenständig bestrebt diese Position zu halten. Daher macht es aus meiner Sicht wenig Sinn, den Winkelwert erst in einen hochkomplexen Floatpoint ( Delta 2 ) umzuwandeln, wenn man dann ohnehin nur je nach Servo 2048 Winkelschritte nutzen kann, oder vom Servo unterstützt werden.

    Franky

  • Hallo an alle,

    erst mal vielen Dank an euch!

    Ich habe hier die Servos von Carson CS3 Reflex. Nach Herstellerangaben mit einer Zugkraft von 2 DaN angegeben und können kontinuierlich drehen.

    Mit meinem Servotester funktioniert das auch.

    Ich bin nicht der Guru bei Python und muss mich bei vielen Sachen noch einlesen. Ich programmiere sonst mit Step 7 oder TIA.

    Leider habe ich zu spät mit Python angefangen. Ich bin auch schon 78 Jahre alt und versuche doch noch was neues.

    Auch mit Tkinter bin ich noch Neuling.

    Damals nach meinem Studium an der RWTH habe ich Assembler programmiert, das war der Einstieg bei den meisten SPS-Programme.

    Das meiste davon habe ich inzwischen vergessen.

    Ich hoffe auf weitere Hilfe bei diesem Programm. Es soll einen Roboter steuern,

    Gruss

    Bernd

  • Moinsen,

    Wie ich der Anleitung bei Carson entnehmen konnte, handelt es sich um ein analoges Servo. Also eine Feinere Auflösung des Bereiches 0-180 Grad mit mehr als 2048 Schritten ist somit vollkommen unnötig.
    Das heist, du aber hier ist dann wieder Dennis89 gefragt, ob man diesen Servozyklus soweit manipulieren könnte, das die Aufteilung des Tastverhältnisses des PWM Signals mathematisch beschnitten wird. Also nicht alles Nachkommastellen innerhalb dieses Class-Objektes zur PWM Signal Generierung genutzt werden.

    @bernhardjunk wie du in dem von gezeigten Link sehen kannst wird bei solchen Servos eine Grundtakt von 50 Hz gleichbedeutend einer Periodendauer von 20 ms verwendet. Dann beträgt aber der tatsächliche Nutzsignalanteil nur den Bereich des Tastverhältnisses von 1 ms bis 2 ms. Dieser Bereich von dieser einen Millisekunde um den gesamten Stellbereich abzudecken, dann in µs muss nur eine Genauigkeit ausweisen, die diese 1ms in maximal 2048 Schritte oder 1024 Schritte unterteilt. Alles andere kann von deinem Servo nicht wirklich umgesetzt werden, und das Servo versucht durch das ständige Neusetzen des Tastverhältnisses die Schwankungen aus dem analogen Winkelmesswert ( intern ) und dem PWM Signal auszugleichen.

    Ausgehend vom Nutzbereich: 0 bis 180 Grad musst du Selektierung machen. Bleiben wir mal bei 1024 Steps also einer nutzbaren Auflösung von 180 Grad / 1024 Steps.

    Damit müsste der Aufruf wie von Dennis89 beschrieben und nach der Initiierung mit

    Code
    pwm1 = GPIO.PWM(SERVO_PIN1, 50)
    servo1 = Servo(pwm1, name ='Drehteller', angle_start = 0)

    dann in der Zeile zu seinem letzten Code #6 unterer Teil Zeile 31 lauten

    Python
    command=partial(servo1.set, angle),

    [ Code ungetestet ]

    In der Folge wird nur dann ein neues, geändertes PWM Signal erzeugt, wenn die vorgegeben Winkelabweichung größer 0,1 Grad ist, und der Winkel im zulässigen Bereich liegt.

    Franky

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!