Schrittmotor soll eine vorgegebene Anzahl an Schritten mit einer vorgegebenen Geschwindigkeit abfahren

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo Raspberry-Pi Forum,

    für mein Projekt besitze ich einen Schrittmotor mit einer Auflösung von 400 Steps/Rev. (0,9 °/Step). Es handelt sich hierbei um einen NEMA 23, der mittels dem Driver HBS57 als closed-loop stepper ausgeführt ist. Hier der Link zu dem Motor. https://de.aliexpress.com/item/330276652…2e-53f4e10a3644  

    Mein Ziel ist es nun, dass mein Schrittmotor einen gewissen Absolutwinkel (Anzahl an Schritten) mit einer definierten Geschwindigkeit (Drehzahl) abfährt. Darüber habe ich mir schon Gedanken gemacht und habe eine Lösung ausgearbeitet. Ich bin mir aber unsicher, ob diese Lösung eine "schöne" und effektive Lösung ist. Ich möchte diese euch kurz aufzeigen und eure Meinung dazu hören.

    Ich möchte in meinem Programm den Absolutwinkel [°] und die Drehzahl [U/min] vorgeben, diese dienen als bekannt.

    Die Anzahl der Impulse, die mein Schrittmotor verfahren muss ergibt sich, indem der gewollte Absolutwinkel durch die Schrittauflösung des Motors geteilt wird.

    Anzahl benötigter Impulse = Absolutwinkel / Schrittauflösung
    [°] / [°/Steps]

    Die Drehzahl des Motors wird über die Frequenz der 5V-Pulse am Treiber Eingang bestimmt. Drehzahl des Motors ist proportional zu der Frequenz der Impulse am Pul- Eingang des Treibers. Über die Soll-Drehzahl, die ich vorgeben möchte kann ich die Frequenz [Hz] der Impulse mit folgender Formel berechnen.

    f = (Soll-Drehzahl * Schrittauflösung)/60

    [U/min] / [Steps/Rev.]

    Da nun die Anzahl der benötigten Impulse und die Frequenz mit dem die Impulse eingehen bekannt ist, kann ich nun eine Zeit [s] berechnen. Durch die Division der benötigten Impulse und der Frequenz der Impulse weiß ich, wie lange ich die Pulse am Eingang des Treibers des Motors anlegen muss, bis die benötigte Anzahl an Schritten und so den Absolutwinkel erreicht sind.

    t = Anzahl benötigter Impulse / f

    Ich würde das dann so realisieren. Ich würde nach ablaufen der oben berechneten Zeit eine boolsche Variable auf True setzen und dadurch den Ausgang der Impuls-Signale abschalten.

    Eine weitere Überlegung von mir war, das Impulssignal zusätzlich an einem Eingang anzulegen und mittels einem Timer die steigenden Flanken zu zählen. Problem hierbei leider ist, dass die Eingänge max. eine Frequenz von 400 Hz erkennen können. Die Impuls-Signale die an den Treiber des Motors gesendet werden, haben bis zu 15 kHz.

    Das waren meine Ideen zu dem Thema. Ich bin mir nicht sicher wie genau diese ist und wie viel Abweichungen im Betrieb entstehen könnten.

    Könnt ihr mit eurer Erfahrung und Know How einschätzen, ob dieses Vorgehen möglich ist. Habt ihr vielleicht eine bessere Herangehensweise?

    Vielen Dank für eure Antworten.

    Gruß Aron

    Einmal editiert, zuletzt von aron93 (14. November 2019 um 11:53)

  • Schrittmotor soll eine vorgegebene Anzahl an Schritten mit einer vorgegebenen Geschwindigkeit abfahren? Schau mal ob du hier fündig wirst!

  • Du musst die drei Eingänge (PUL/DIR/ENA) des Controllers koordinieren.

    Mit PUL steuerst du die Schritte einmal LOW-HIGH-LOW ist ein Schritt.

    DIR ist die Richtung in der sich der Motor bewegen soll.

    Und mit ENA schaltest du den Motor ein.

    Achte darauf, dass die +Eingänge eine gemeinsame Verbindung zu +5V haben. Was den RPi schon an die Grenzen der Belastbarkeit seiner Pins bringt. Besser wäre es, wenn du einen Transistor/FET dazwischen schalen würdest.

    Du kannst dir gerne auch die Encoder Signale des Motors anschauen. der Closed-Loop-Controller sollte verhindern, dass ein Schritt nicht ausgeführt wird.

    Glaube ersetzt kein Wissen

  • 15 kHz ist glaube ich schon eine Hausnummer. Da brauchst Du schon eine hohe Versorgungsspannung um die Induktivitäten der Motorwicklungen zu überwinden.

    Außerdem mußt Du den Motor langsam beschleunigen. Sonnst ist die Massenträgheit der bewegten Masse zu hoch und der Motor verliert Schritte.

  • 15 kHz ist glaube ich schon eine Hausnummer. Da brauchst Du schon eine hohe Versorgungsspannung um die Induktivitäten der Motorwicklungen zu überwinden.

    Außerdem mußt Du den Motor langsam beschleunigen. Sonnst ist die Massenträgheit der bewegten Masse zu hoch und der Motor verliert Schritte.

    ja die 15 kHz ist schon das maximale, aber das werde ich glaube ich nicht benötigen. Im Nennbetrieb liegt die Frequenz bei so 10kHz. Ja da hast du recht, ich muss mir auf jeden Fall noch Gedanken machen, wie ich die Beschleunigungsrampen am besten umsetzte. Hast du da eine Faustregel dafür?

    Wie findest du die Lösung, die ich oben Beschrieben habe? Ich möchte nicht komplett 360Grad drehen sondern z.B. nur 180Grad. Er soll dann zwischen 90 und -90 Grad sich hin und herbewegen mit einer Geschwindigkeit, die ich vorgebe. Ich habe das in codeys versucht, aber es hat nicht so funktioniert. Habe die Zeit (s. Oben) berechnet und eine while Schleife auch wenn aufgebaut. Zunächst setzte ich den direction Eingang des Motor Treibers true (rechtsstehend). Mit einem TON lasse ich die berechnete Zeit ablaufen. Nachdem setzte ich den direction wieder auf false (linksstehend). Lasse den TON wieder ablaufen und setzte danach direction wieder auf true und alles beginnt wieder von vorne.

    Die Schleife macht leider nicht, das was ich möchte. Vorallem der TON funktioniert nicht wirklich.

  • Mit codesys hab ich noch nicht gearbeitet. Tut mir Leid.

    Kannst trotzdem mal Deinen Quelltext hier rein setzen.

    An Deiner Stelle würde ich das Prog erstmal mit 10 HZ laufen lassen. Da sehe ich noch keine Probleme. Wenn es damit läuft kannst Du anfangen die Drehzahl nochzuregeln.

    15kHz sind bei Deinem Motor 37,5U/sec =2.250 U/min. Richtig? Einen so schnellen Schrittmotor hab ich noch nicht gesehen....

  • Mit codesys hab ich noch nicht gearbeitet. Tut mir Leid.

    Kannst trotzdem mal Deinen Quelltext hier rein setzen.

    An Deiner Stelle würde ich das Prog erstmal mit 10 HZ laufen lassen. Da sehe ich noch keine Probleme. Wenn es damit läuft kannst Du anfangen die Drehzahl nochzuregeln.

    15kHz sind bei Deinem Motor 37,5U/sec =2.250 U/min. Richtig? Einen so schnellen Schrittmotor hab ich noch nicht gesehen....

    ja genau. Ist die max. Drehzahl, die der Hersteller angibt.

    Anbei der Code-Teil. Die oberen Zeilen befassen sich nur mit der Konfiguration des PWM-Kanals und habe ihn deshalb rausgeschnitten. Die Variable MyTime ist die mit der Formel t = Anzahl benötigter Impulse / f berechnete Zeit, diese übergebe ich einen TOn-Zeitverzögerungsbaustein. Die Boolsche Variable Direction ist mit dem Direction Eingang des MotorTreibers verbunden. False bedeutet rechtsdrehend und true linksdrehend.

    Ich versuche das wiederholte hin und her drehen mit einer while-Schleife zu realisieren. Zu Beginn ist Direction False und der Motor dreht rechts. Mit dem TON-Zeitverzögerungsbaustein möchte ich nun Direction so lange false gesetzt lassen bis dieser die gewünschten Steps erreicht hat. Nach dem abgelaufenen TON wird dann Direction auf True gesetzt und soll dann in die anderen Richtung wieder zurückfahren mit gleicher Schrittanzahl. Dies soll sich dann beliebig oft wiederholen. Wenn ich das nun simuliere passiert überhaupt nicht was ich möchte.


  • Wenn du Code postet, dann bitte nicht als Bild, verwende besser dir Code-Tags (drittes Icon von rechts).

    'Was du suchst ist die Rampen-Funktion. Denke dabei auch an das Bremsen.

    Mir ist nicht ganz klar, für was du eine Zeitverzögerungsbaustein brauchst. Welches IC?

    Glaube ersetzt kein Wissen

  • Mir ist nicht ganz klar, für was du eine Zeitverzögerungsbaustein brauchst. Welches IC?

    Ich Versuche gerade einen Funktionsbaustein in Codesys zu programmieren. Als Input-Variablen dienen Speed, AbsoluteAngle und Enable. Mit Enable soll der Baustein einfach leicht aktiviert und dekativiert werden. Mit Speed möchte ich eine Drehzahl in U/min vorgeben mit der Schrittmotor drehen soll. Mit der Variable AbsoluteAngle soll man dann in der Lage sein, ein Winkel zu wählen, den der Motor dann bzgl. der Anfangsposition abfahren soll. Das ganze soll dann in einem Dauerversuch stattfinden, dass heißt der Motor soll Absolutwinkel mit vorgegeben Geschwindigkeit anfahren und dann mittels einem Richtungswechsel wieder zur Anfangsposition zurückfahren. Diese Richtungswechsel sollen dann beliebig lange durchgeführt werden.

    Meine Idee zur Realisierung habe ich im ersten Post beschrieben. In Speed gibt man eine Drehzahl in U/min ein, die dann durch einen Programmteil in ein entsprechendes Puls-Signal mit der benötigten Frequenz umgesetzt wird. Der Absolutwinkel der abgefahren werden soll ergibt sich aus einer gewissen Anzahl an Schritten des Motors (0,9°/Schritt).

    Im Program berechne ich die benötigte Anzahl der Schritte zur Erreichung des Absolutwinkels mit der Formel
    Anzahl benötigter Impulse = Absolutwinkel / Schrittauflösung ([°] / [°/Steps]). Die Frequenz der Impulse für die Drehzahlsteuerung kann ich sehr leicht durch folgende Formel berechnen f = (Soll-Drehzahl * Schrittauflösung)/60 ([U/min] / [Steps/Rev.]).

    Da nun die Anzahl der benötigten Impulse und die Frequenz mit dem die Impulse eingehen bekannt ist, kann ich nun eine Zeit [s] berechnen, die der Schrittmotor braucht, um den Absolutwinkel zu erreichen. t = Anzahl benötigter Impulse / f [s]

    Meine Idee war es nun, in einer Schleife diesen Richtungswechsel (Anfangsposition-AbsoluteAngle) in einer Schleife zu realisieren. Indem ich an dem Direction eingang, ständig zwischen TRUE und FALSE wechsle. Da aber erst die Zeit t ablaufen muss, bis der Motor den Absolutwinkel erreicht hat möchte ich da eine Zeitverzögerung einbauen, die dann genau das realisiert. Bin mir aber nicht sicher, ob das eine elegante Lösung ist.


    Aber es klappt leider nicht so wie ich das möchte. Ist da meine ganze herangehensweise mit dem Umrechnen der Formeln einfach schlecht? Gibt es andere Möglichkeiten?

    Danke für eure Hilfe.


  • Wenn ich dich richtig verstehe, dann übergibst du einem Programm wann und wie schnell es an eine bestimmte Position fahren soll. Das Problem dabei ist nun, du bekommst keine Rückmeldung wann das Ziel erreicht wurde? Gibt es keine Möglichkeit, dass dir MoveToPosition das Ende mitteilt?

    Glaube ersetzt kein Wissen

  • Wenn ich dich richtig verstehe, dann übergibst du einem Programm wann und wie schnell es an eine bestimmte Position fahren soll. Das Problem dabei ist nun, du bekommst keine Rückmeldung wann das Ziel erreicht wurde? Gibt es keine Möglichkeit, dass dir MoveToPosition das Ende mitteilt?

    der Code zu move position ist oben im Anhang. Ja genau ich habe keinen Encoder, der mir Auskunft gibt wann mein Ziel erreicht ist. Deshalb versuche ich es über die Zeit machen (bei bekannter Drehzahl und absolutwinkel) . Die Ungenauigkeit, die bei auftretenden Schnittveruste entstehen kann, nehme ich in Kauf.

    Gibt es eine andere Möglichkeit die zeitverzögerung zu realisieren?

  • Du kannst den Encoder vom Schrittmotor abgreifen und die Schritte zählen.

    Die Ungenauigkeit, die bei auftretenden Schnittveruste entstehen kann, nehme ich in Kauf.

    Bei Dauerversuchen wird das nicht funktionieren, denn du wirst mit dieser Methode immer eine Differenz von links zu rechts haben.

    Glaube ersetzt kein Wissen

  • Hallo aron93,

    für eine Low-Levelsteuerung auf Impulsbasis ist CODESYS der falsche Ansatz. Einerseits, weil Du bereits auf einem blanken Linux keine zeitlich sauberen Signalfolgen ausgeben kannst (Thema Linux Scheduler), zweitens, weil Dir die CODESYS Runtime mit ihrem eigenen Prozeßmodell nochmals einen Knüppel zwischen die Beine haut, was das Threading anbelangt. Die CODESYS Runtime verrät nämlich nicht, wie sie Ihre Prozesse im Detail scheduled. Das verwässert das Konzept des Linux-Scheduling nochmals.

    Eine halbwegs brauchbare Lösung (wenn's denn unbedingt ein Raspi sein muß) könntest Du erzielen, wenn Du ein externes C-Programm schreibst, welches den Low-Levelteil der Pulsausgabe übernimmt und dieses über CODESYS als externes Programm aufrufst (siehe SysProcessExecuteCommand). So ähnlich mache ich das auch in meinem CODESYS-Treiber zum Bitbangen eines 433MHz Sender Modules. Wie das am Ende unter Codesys aussieht, kannst Du >>> hier <<< entnehmen. Der Mechanismus des Aufrufes eines externen Programmes ist >>> hier<<< skizziert.

    Besser wäre es jedoch, man überließe die Pulsgenerierung einem Arduino und spräche diesen per Raspi (z.B. seriell) an. Entweder kümmert man sich dann selbst um die Impulserzeugung oder installiert eine Marlinsoftware und verwendet die G-Code Befehlsschnittstelle. Beim letzten Ansatz hätte man allfällige Probleme von Beschleunigung, Geschwindigkeit, relativer/absoluter Positionierung, Endschalter... gleich mit erschlagen. M.E. der schnellste und sauberste Weg, einer technischen Umsetzung. Will man lernen, dann gehen auch die Wege der manuellen Arduino-Programmierung oder auch das direkte Steuern vom Raspi.

    Schöne Grüße und viel Erfolg,

    schnasseldag

  • Danke für die ausführliche Antwort. Ich werde mich mit den 2 Ideen mal beschäftigen und schauen wie ich das in meinem Projekt realisieren könnten. Besten Dank für den guten Input.

    Gruß

    Aron

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!