Untitled
unknown
plain_text
5 months ago
6.8 kB
2
Indexable
import sys import termios import tty 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 == 1 and self.limit_switch.is_pressed) or (self.position <= 0 and direction == 0): print("Limit switch reached or position is 0, stopping motor.") break if self.max_position is not None: if (direction == 0 and self.position >= self.max_position): print(f"Max position of {self.max_position} reached while moving backwards, stopping motor.") break elif (direction == 1 and self.position <= 0): print(f"Min position (0) reached while moving forward, 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 # Minska position när den går framåt (direction=1) else: self.position += 1 # Öka position när den går bakåt (direction=0) def calibrate(self): """ Kalibrerar motorn genom att snurra framåt (direction=1) tills limit switchen aktiveras. """ print("Starting calibration...") while not self.limit_switch.is_pressed: self.step(1, direction=1, min_delay=0.005, max_delay=0.005) # Långsamt framåt mot knappen print("Calibration complete. Position reset to 0.") self.position = 0 # Återställ positionen till 0 def calibrate_max_position(self): """ Kalibrerar motorn genom att flytta till position 0 och sedan bakåt tills användaren trycker på en tangent. Max positionen sparas efter att användaren stoppar motorn med en knapptryckning. """ # Kalibrera först position 0 self.calibrate() print("Now moving towards max position (press any key to stop)...") while not self._key_pressed(): self.step(1, direction=0, min_delay=0.005, max_delay=0.005) # Långsamt bakåt (direction=0) # När användaren trycker på en knapp, sätt positionen som max position self.max_position = self.position print(f"Calibration of max position complete. Max position set to {self.max_position} steps.") def move_to_max_position(self): """ Roterar motorn bakåt (direction=0) tills max position uppnås. """ if self.max_position is not None: print(f"Moving to max position: {self.max_position} steps.") while self.position < self.max_position: self.step(1, direction=0, min_delay=0.005, max_delay=0.005) # Långsamt bakåt mot max position print(f"Reached max position: {self.max_position} steps.") else: print("Max position is not set.") 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) def _key_pressed(self): """ Kontrollera om någon tangent är tryckt för att stoppa kalibreringen. """ fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: tty.setraw(sys.stdin.fileno()) rlist, _, _ = select([sys.stdin], [], [], 0) if rlist: sys.stdin.read(1) return True return False finally: termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) # Exempel på hur man använder klassen if __name__ == "__main__": motor = StepperMotor(dir_pin=20, step_pin=21, limit_switch_pin=16) # Maxposition inte inställd ännu try: motor.calibrate_max_position() # Kalibrera både position 0 och max position print(f"Position after max calibration: {motor.position}") print(f"Max position set to: {motor.max_position}") finally: print("Motorkontroll avslutad.")
Editor is loading...