class AzimuthController: DIRECTION_GPIO = 38 PULSE_GPIO = 40 HOME_GPIO = 22 MICROSTEPS = 400 GEAR_RATIO = 48 LEFT_DIRECTION = True RIGHT_DIRECTION = not LEFT_DIRECTION HOMING_DIRECTION = LEFT_DIRECTION BACKLASH_STEPS = 12 def __init__(self): GPIO.setup(self.HOME_GPIO, GPIO.IN, pull_up_down = GPIO.PUD_UP) self.__stepper = Stepper(self.MICROSTEPS * self.GEAR_RATIO, self.DIRECTION_GPIO, self.PULSE_GPIO, self.BACKLASH_STEPS) steps = 0 while self.is_home(): self.__stepper.pulse(self.HOMING_DIRECTION) steps += 1 if (steps > self.total_steps()): raise ValueError("Cannot home the azimuth stepper. It is likely not moving or the sensor is broken.") while not self.is_home(): self.__stepper.pulse(self.HOMING_DIRECTION) steps += 1 if (steps > self.total_steps()): raise ValueError("Cannot home the azimuth stepper. It is likely not moving or the sensor is broken.") self.__stepper.reset_position() def is_home(self): return not GPIO.input(self.HOME_GPIO) def position(self): return self.__stepper.position() def total_steps(self): return self.__stepper.total_steps() def move_left(self, steps): return self.move(self.LEFT_DIRECTION, steps) def move_right(self, steps): return self.move(self.RIGHT_DIRECTION, steps) def move(self, direction, steps): self.__stepper.move(direction, steps) return True def move_to(self, position, max_steps = sys.maxint): if position < 0 or position >= self.total_steps(): raise ValueError("Invalid position") steps_from_left = (position - self.position()) % self.total_steps() steps_from_right = (self.position() - position) % self.total_steps() if steps_from_left <= steps_from_right: self.move(self.LEFT_DIRECTION, min(steps_from_left, max_steps)) return steps_from_left <= max_steps else: self.move(self.RIGHT_DIRECTION, min(steps_from_right, max_steps)) return steps_from_right <= max_steps
class ElevationController: DIRECTION_GPIO = 36 PULSE_GPIO = 32 # There are ~150 degrees between the two home sensors HOME_DOWN_GPIO = 24 HOME_UP_GPIO = 26 MICROSTEPS = 400 GEAR_RATIO = 48 DOWN_DIRECTION = True UP_DIRECTION = not DOWN_DIRECTION BACKLASH_STEPS = 12 def __init__(self): GPIO.setup(self.HOME_DOWN_GPIO, GPIO.IN, pull_up_down = GPIO.PUD_UP) GPIO.setup(self.HOME_UP_GPIO, GPIO.IN, pull_up_down = GPIO.PUD_UP) self.__stepper = Stepper(self.MICROSTEPS * self.GEAR_RATIO, self.DIRECTION_GPIO, self.PULSE_GPIO, self.BACKLASH_STEPS) steps = 0 while self.is_home_down(): self.__stepper.pulse(self.UP_DIRECTION) steps += 1 if (steps > self.__stepper.total_steps()): raise ValueError("Cannot home the elevation stepper. It is likely not moving or the sensor is broken.") while not self.is_home_down(): self.__stepper.pulse(self.DOWN_DIRECTION) steps += 1 if (steps > self.__stepper.total_steps()): raise ValueError("Cannot home the elevation stepper. It is likely not moving or the sensor is broken.") steps = 0 self.__amplitude = 0 while not self.is_home_up(): self.__stepper.pulse(self.UP_DIRECTION) steps += 1 self.__amplitude += 1 if (steps > self.__stepper.total_steps()): raise ValueError("Cannot home the elevation stepper. It is likely not moving or the sensor is broken.") self.__stepper.reset_position() def is_home(self): return self.is_home_down() or self.is_home_up() def is_home_down(self): return not GPIO.input(self.HOME_DOWN_GPIO) def is_home_up(self): return not GPIO.input(self.HOME_UP_GPIO) def position(self): position = float(self.__stepper.position()) / self.amplitude() if position < 0 or position > 1: raise ValueError("Invalid position about to be returned: " + position) return position def amplitude(self): return self.__amplitude def move_to(self, percentage_amplitude, max_delta = 1.0): if percentage_amplitude < 0 or percentage_amplitude > 1: raise ValueError("Percentage of amplitude must be between 0 and 1: " + str(percentage_amplitude)) steps = int((percentage_amplitude - self.position()) * self.amplitude()) max_steps = int(max_delta * self.amplitude()) direction = self.UP_DIRECTION if steps < 0 else self.DOWN_DIRECTION self.__stepper.move(direction, min(abs(steps), max_steps)) return abs(steps) <= max_steps