Hallo!
Wie der Titel von diesem Beitrag schon aussagt, möchte ich einen Schrittmotor Kosinus förmig auf eine maximal Geschwindigkeit beschleunigen.
Um einen Schrittmotor zu beschleunigen, muss ja zwischen den einzelnen Schritten die Wartezeit immer weiter verkürzt werden.
Zu Beginn möchte ich also eine Wartezeit zwischen den Schritten von 0,005 sec haben und bei der maximalen Geschwindigkeit eine Wartezeit von 0,0005 sec.
Für die Beschleunigung soll in diesen Beispiel 30 Schritte verwendet werden.
Hierfür habe ich eine Kosinus Funktion ausgelegt, welche folgendermaßen verläuft:
Um diese in Python umzusetzen habe ich folgenden Code geschrieben wo bei der Funktion perform_steps eine Schrittanzahl übergeben wird:
def __init__(self, data, out_pin_1: int, out_pin_2: int, out_pin_3: int, out_pin_4: int, kp: float, ki: float, zero_sensor_pin: int):
super().__init__()
self._data = data
self._kp = kp
self._ki = ki
self._zero_sensor_pin = zero_sensor_pin
self._steps_per_revolution = 200
self._max_acc_delay=0.0005
self._min_acc_delay=self._delay=0.005
self._acc_steps=30
self._step_pins = [out_pin_1,out_pin_2,out_pin_3,out_pin_4]
self._seq = [[GPIO.HIGH,GPIO.LOW,GPIO.LOW,GPIO.HIGH],[GPIO.HIGH,GPIO.LOW,GPIO.LOW,GPIO.LOW],[GPIO.HIGH,GPIO.HIGH,GPIO.LOW,GPIO.LOW],[GPIO.LOW,GPIO.HIGH,GPIO.LOW,GPIO.LOW],[GPIO.LOW,GPIO.HIGH,GPIO.HIGH,GPIO.LOW],[GPIO.LOW,GPIO.LOW,GPIO.HIGH,GPIO.LOW],[GPIO.LOW,GPIO.LOW,GPIO.HIGH,GPIO.HIGH],[GPIO.LOW,GPIO.LOW,GPIO.LOW,GPIO.HIGH]]
GPIO.setup(self._step_pins[0], GPIO.OUT)
GPIO.setup(self._step_pins[1], GPIO.OUT)
GPIO.setup(self._step_pins[2], GPIO.OUT)
GPIO.setup(self._step_pins[3], GPIO.OUT)
GPIO.output(self._step_pins[0], GPIO.LOW)
GPIO.output(self._step_pins[1], GPIO.LOW)
GPIO.output(self._step_pins[2], GPIO.LOW)
GPIO.output(self._step_pins[3], GPIO.LOW)
def perform_steps(self, amount_steps: int, direction: bool):
print(amount_steps)
acc_steps=self._acc_steps
diff=self._min_acc_delay-self._max_acc_delay
a=(diff)/2
if((2*self._acc_steps)>amount_steps):
old_acc_steps=acc_steps
acc_steps=amount_steps/2
#Reduziert maximale Geschwindigkeit prozentual mit der Strecke die zur Beschleunigung verfahren wird
a=a*(old_acc_steps-acc_steps)/old_acc_steps
t=2*acc_steps
c=self._min_acc_delay-diff/2
#Beschleunigungsfunktion
acc_func=lambda step: a*math.cos(2*math.pi/t*step)+c
dacc_func=lambda step: a*math.cos(2*math.pi/t*(step+t/2))+c
print(acc_steps)
print(t)
print(c)
print(a)
# Rampe am Anfang der Drehung
for step in range(acc_steps):
self._delay = acc_func(step)
# Gehe durch die Schrittsequenz und schalte die Pins entsprechend ein und aus
for seq_part in range(0,7):
for pin in range(0, 4):
GPIO.output(self._step_pins[pin],self._seq[seq_part][pin])
time.sleep(self._delay)
print("1"+str(self._delay))
# Drehung des Motors mit konstanter Geschwindigkeit
for step in range(amount_steps - 2 * acc_steps):
self._delay = acc_func(acc_steps)
# Gehe durch die Schrittsequenz und schalte die Pins entsprechend ein und aus
for seq_part in range(0,7):
for pin in range(0, 4):
GPIO.output(self._step_pins[pin],self._seq[seq_part][pin])
time.sleep(self._delay)
print("2"+str(self._delay))
# Rampe am Ende der Drehung
for step in range(self._acc_steps):
self._delay = dacc_func(step)
# Gehe durch die Schrittsequenz und schalte die Pins entsprechend ein und aus
for seq_part in range(0,7):
for pin in range(0, 4):
GPIO.output(self._step_pins[pin],self._seq[seq_part][pin])
time.sleep(self._delay)
print("3: "+str(self._delay))
GPIO.output(self._step_pins[0], GPIO.LOW)
GPIO.output(self._step_pins[1], GPIO.LOW)
GPIO.output(self._step_pins[2], GPIO.LOW)
GPIO.output(self._step_pins[3], GPIO.LOW)
Display More
Die durch die Funktion berechneten Werte entsprechen exakt denen wie ich sie in Excel zuvor berechnet habe und somit auch den Werten wie sie im ersten Diagramm dargestellt sind.
Ich würde nach diesem Code folgenden Geschwindigkeitsverlauf des Motors erwarten (Skalierung in Y-Achse ist unrelevant ist nur eine beispielhafte Darstellung):
Tatsächlich aber fährt der Motor zu Beginn die Kurve so wie er soll aber sobald er die kleinste Wartezeit dauerhaft annimmt verfährt er mit einem Ruck viel schneller. Er geht also nicht flüssig in die höchste Geschwindigkeit über. Das schaut dann ungefähr so aus:
Zur Hardware:
Ich verwende einen L298N Motortreiber sowie einen Nema 17 Schrittmotor.
Des Weiteren verwende ich einen Raspberry Pi 4.
Der Aufbau gleicht folgender Darstellung:
Anzumerken ist dabei vllt. noch dass ich das gleich Problem auch bei einer einfacheren Beschleunigungsrampe hatte also einer linearen Beschleunigung, weshalb ich glaube dass es kein Softwarefehler sonder eher was mit der Hardware zu tun hat.
Für Hilfe wäre ich sehr dankbar.
Mit freundlichen Grüßen