Untitled
unknown
plain_text
a year ago
4.9 kB
4
Indexable
from time import sleep
from gpiozero import OutputDevice, Button
class StepperMotor:
def __init__(self, dir_pin, step_pin, limit_switch_pin, steps_per_revolution=200, max_position=None):
self.dir_pin = OutputDevice(dir_pin)
self.step_pin = OutputDevice(step_pin)
self.limit_switch = Button(limit_switch_pin, pull_up=True) # Pull-up aktiverad om knappen är normalt öppen
self.steps_per_revolution = steps_per_revolution
self.position = 0 # Håller koll på positionen i steg
self.max_position = max_position # Maximal tillåten position
def step(self, steps, direction=1, min_delay=0.001, max_delay=0.01, ramp_steps=10):
"""
Gör stegen med motorn och ändrar hastigheten mellan min och max delay.
Uppdaterar positionen efter varje steg. Stoppar motorn om max position uppnås.
:param steps: Antal steg att ta
:param direction: 1 för framåt, 0 för bakåt
:param min_delay: Minsta fördröjning mellan pulser (snabbaste hastighet)
:param max_delay: Största fördröjning mellan pulser (långsammaste hastighet)
:param ramp_steps: Antal steg som används för att accelerera och decelerera
"""
# Ställ in riktning
self.dir_pin.value = direction
# Accelerations- och deaccelerationsramper
def calculate_delay(step, total_steps, min_d, max_d, ramp_s):
if step < ramp_s: # Accelerera
return max_d - (step / ramp_s) * (max_d - min_d)
elif step >= total_steps - ramp_s: # Decelerera
return max_d - ((total_steps - step) / ramp_s) * (max_d - min_d)
else: # Konstant hastighet
return min_d
for current_step in range(steps):
# Kontrollera om limit-switchen aktiverats eller om max position har nåtts
if (direction == 0 and self.limit_switch.is_pressed) or (self.max_position is not None and self.position >= self.max_position and direction == 1):
print("Max position reached or limit switch activated, stopping motor.")
break
# Beräkna delay baserat på stegets position
delay = calculate_delay(current_step, steps, min_delay, max_delay, ramp_steps)
# Skicka pulser
self.step_pin.on()
sleep(delay)
self.step_pin.off()
sleep(delay)
# Uppdatera positionen
if direction == 1:
self.position += 1
else:
self.position -= 1
# Kontrollera om motorn ska stoppas på grund av max position
if self.max_position is not None and self.position >= self.max_position:
print(f"Position limit of {self.max_position} reached, stopping motor.")
break
def calibrate(self):
"""
Kalibrerar motorn genom att snurra tills limit switchen aktiveras.
"""
print("Starting calibration...")
while not self.limit_switch.is_pressed:
self.step(1, direction=0, min_delay=0.005, max_delay=0.005) # Långsamt bakåt mot knappen
print("Calibration complete. Position reset to 0.")
self.position = 0 # Återställ positionen till 0
def rotate(self, rotations, direction=1, min_delay=0.001, max_delay=0.01, ramp_steps=10):
"""
Roterar motorn ett visst antal varv och justerar hastigheten under rotation.
Uppdaterar också positionen. Stoppar motorn om max position uppnås.
:param rotations: Antal varv att snurra
:param direction: 1 för framåt, 0 för bakåt
:param min_delay: Minsta fördröjning mellan pulser (snabbaste hastighet)
:param max_delay: Största fördröjning mellan pulser (långsammaste hastighet)
:param ramp_steps: Antal steg som används för att accelerera och decelerera
"""
steps = int(rotations * self.steps_per_revolution)
self.step(steps, direction, min_delay, max_delay, ramp_steps)
# Exempel på hur man använder klassen
if __name__ == "__main__":
motor = StepperMotor(dir_pin=20, step_pin=21, limit_switch_pin=16, max_position=1000) # Exempel med maxposition 1000 steg
try:
motor.calibrate() # Kalibrera motorn mot limit switch
motor.rotate(5, direction=1, min_delay=0.001, max_delay=0.01, ramp_steps=50) # Försök att rotera 5 varv
print(f"Position after forward rotation: {motor.position}")
sleep(1)
motor.rotate(1, direction=0, min_delay=0.001, max_delay=0.01, ramp_steps=50) # Roterar ett varv bakåt
print(f"Position after backward rotation: {motor.position}")
finally:
print("Motorkontroll avslutad.")
Editor is loading...