Example #1
0
    def __init__(self,
                 channel,
                 pulse_width_start,
                 pulse_width_stop,
                 init_angle,
                 turnoff_timeout=0):
        """Define a new software controllable servo with adjustable speed control

        Keyword arguments:
        pulse_width_start -- The minimum pulse width defining the lowest angle
        pulse_width_stop -- The maximum pulse width defining the biggest angle
        init_angle -- Initial angle that the servo should take when it is powered on. Range is 0 to 180deg
        turnoff_timeout -- number of seconds after which the servo is turned off if no command is received. 0 = never turns off
        """

        self.pulse_width_start = pulse_width_start
        self.pulse_width_stop = pulse_width_stop
        self.turnoff_timeout = turnoff_timeout

        self.current_pulse_width = init_angle * (
            self.pulse_width_stop -
            self.pulse_width_start) / 180.0 + self.pulse_width_start
        self.last_pulse_width = self.current_pulse_width

        self.queue = JoinableQueue(1000)
        self.lastCommandTime = 0

        self.t = Thread(target=self._wait_for_event)
        self.t.daemon = True
        self.running = True
        self.t.start()

        self.pwm = PWM_pin(channel, 100, self.current_pulse_width)

        # Set up the Shift register for enabling this servo
        if channel == "P9_14":
            shiftreg_nr = 3
        elif channel == "P9_16":
            shiftreg_nr = 2
        else:
            logging.warning(
                "Tried to assign servo to an unknown channel/pin: " +
                str(channel))
            return

        ShiftRegister.make()
        self.shift_reg = ShiftRegister.registers[shiftreg_nr]
        self.set_enabled()
Example #2
0
    def __init__(self, channel, shiftreg_nr, pulse_width_start, pulse_width_stop, init_angle, turnoff_timeout=0):
        """Define a new software controllable servo with adjustable speed control

        Keyword arguments:
        pulse_width_start -- The minimum pulse width defining the lowest angle
        pulse_width_stop -- The maximum pulse width defining the biggest angle
        init_angle -- Initial angle that the servo should take when it is powered on. Range is 0 to 180deg
        turnoff_timeout -- number of seconds after which the servo is turned off if no command is received. 0 = never turns off
        """

        self.pulse_width_start = pulse_width_start
        self.pulse_width_stop = pulse_width_stop
        self.turnoff_timeout = turnoff_timeout

        self.current_pulse_width = (init_angle*(self.pulse_width_stop-self.pulse_width_start)/180.0+self.pulse_width_start)
        self.last_pulse_width = self.current_pulse_width

        self.queue = JoinableQueue(1000)
        self.lastCommandTime = 0

        self.t = Thread(target=self._wait_for_event)
        self.t.daemon = True
        self.running = True
        self.t.start()

        self.pwm = PWM_pin(channel, 100, 0.1)

        # Set up the Shift register for enabling this servo
        ShiftRegister.make()
        self.shift_reg = ShiftRegister.registers[shiftreg_nr]
        self.set_enabled()
Example #3
0
    def __init__(self,
                 channel,
                 pulse_width_min,
                 pulse_width_max,
                 angle_min,
                 angle_max,
                 init_angle,
                 turnoff_timeout=0):
        """Define a new software controllable servo with adjustable speed control

        Keyword arguments:
        pulse_width_min -- The minimum pulse width defining the lowest angle
        pulse_width_max -- The maximum pulse width defining the biggest angle
        init_angle -- Initial angle that the servo should take when it is powered on. Range is 0 to 180deg
        turnoff_timeout -- number of seconds after which the servo is turned off if no command is received. 0 = never turns off
        """

        self.angle_min = angle_min
        self.angle_max = angle_max
        self.angle_total = angle_max - angle_min
        self.pulse_width_min = pulse_width_min
        self.pulse_width_max = pulse_width_max
        self.pulse_width_total = pulse_width_max - pulse_width_min

        self.turnoff_timeout = turnoff_timeout

        self.current_pulse_width = self.angle_to_pulse_width(init_angle)
        self.last_pulse_width = self.current_pulse_width

        self.last_angle = init_angle

        self.pulse_length = 20.0 * 10.0**-3.0  # 20 ms

        logging.debug("Angle min: {} deg".format(self.angle_min))
        logging.debug("Angle max: {} deg".format(self.angle_max))
        logging.debug("Angle tot: {} deg".format(self.angle_total))
        logging.debug("Pulse min: {} ms".format(self.pulse_width_min * 1000.0))
        logging.debug("Pulse max: {} ms".format(self.pulse_width_max * 1000.0))
        logging.debug("Pulse tot: {} ms".format(self.pulse_width_total *
                                                1000.0))

        self.queue = JoinableQueue(1000)
        self.lastCommandTime = 0

        self.t = Thread(target=self._wait_for_event, name="Servo")
        self.t.daemon = True
        self.running = True
        self.t.start()

        # Branch based on channel type.

        if type(channel) == int:  # Revision A
            self.pwm = PWM(channel, 50, self.current_pulse_width)
        else:  # Revision B
            # Set up the Shift register for enabling this servo
            if channel == "P9_14":
                shiftreg_nr = 1
                self.pwm = PWM_pin(channel, 50, self.current_pulse_width)
            elif channel == "P9_16":
                shiftreg_nr = 2
                self.pwm = PWM_pin(channel, 50, self.current_pulse_width)
            else:
                logging.warning(
                    "Tried to assign servo to an unknown channel/pin: " +
                    str(channel))
                return

            ShiftRegister.make(5)
            self.shift_reg = ShiftRegister.registers[shiftreg_nr]
        self.set_enabled()
        self.pwm.set_value(
            self.angle_to_pulse_width(init_angle) / self.pulse_length)
Example #4
0
class Servo:
    def __init__(self,
                 channel,
                 pulse_width_min,
                 pulse_width_max,
                 angle_min,
                 angle_max,
                 init_angle,
                 turnoff_timeout=0):
        """Define a new software controllable servo with adjustable speed control

        Keyword arguments:
        pulse_width_min -- The minimum pulse width defining the lowest angle
        pulse_width_max -- The maximum pulse width defining the biggest angle
        init_angle -- Initial angle that the servo should take when it is powered on. Range is 0 to 180deg
        turnoff_timeout -- number of seconds after which the servo is turned off if no command is received. 0 = never turns off
        """

        self.angle_min = angle_min
        self.angle_max = angle_max
        self.angle_total = angle_max - angle_min
        self.pulse_width_min = pulse_width_min
        self.pulse_width_max = pulse_width_max
        self.pulse_width_total = pulse_width_max - pulse_width_min

        self.turnoff_timeout = turnoff_timeout

        self.current_pulse_width = self.angle_to_pulse_width(init_angle)
        self.last_pulse_width = self.current_pulse_width

        self.last_angle = init_angle

        self.pulse_length = 20.0 * 10.0**-3.0  # 20 ms

        logging.debug("Angle min: {} deg".format(self.angle_min))
        logging.debug("Angle max: {} deg".format(self.angle_max))
        logging.debug("Angle tot: {} deg".format(self.angle_total))
        logging.debug("Pulse min: {} ms".format(self.pulse_width_min * 1000.0))
        logging.debug("Pulse max: {} ms".format(self.pulse_width_max * 1000.0))
        logging.debug("Pulse tot: {} ms".format(self.pulse_width_total *
                                                1000.0))

        self.queue = JoinableQueue(1000)
        self.lastCommandTime = 0

        self.t = Thread(target=self._wait_for_event, name="Servo")
        self.t.daemon = True
        self.running = True
        self.t.start()

        # Branch based on channel type.

        if type(channel) == int:  # Revision A
            self.pwm = PWM(channel, 50, self.current_pulse_width)
        else:  # Revision B
            # Set up the Shift register for enabling this servo
            if channel == "P9_14":
                shiftreg_nr = 1
                self.pwm = PWM_pin(channel, 50, self.current_pulse_width)
            elif channel == "P9_16":
                shiftreg_nr = 2
                self.pwm = PWM_pin(channel, 50, self.current_pulse_width)
            else:
                logging.warning(
                    "Tried to assign servo to an unknown channel/pin: " +
                    str(channel))
                return

            ShiftRegister.make(5)
            self.shift_reg = ShiftRegister.registers[shiftreg_nr]
        self.set_enabled()
        self.pwm.set_value(
            self.angle_to_pulse_width(init_angle) / self.pulse_length)

    def set_enabled(self, is_enabled=True):
        if is_enabled:
            self.shift_reg.add_state(0x01)
        else:
            self.shift_reg.remove_state(0x01)

    def set_angle(self, angle, speed=60, asynchronous=True):
        ''' Set the servo angle to the given value, in degree, with the given speed in deg / sec '''
        angle = max(min(self.angle_max, angle), self.angle_min)
        pulse_width = self.angle_to_pulse_width(angle)
        last_angle = self.last_angle

        logging.debug("Updating angle from {} (pw={}) to {} (pw={}) ".format(
            last_angle, self.last_pulse_width, angle, pulse_width))

        if angle == last_angle:
            return

        t = (math.fabs(angle - last_angle) / speed) / math.fabs(angle -
                                                                last_angle)

        if angle >= last_angle:
            for a in xrange(int(last_angle), int(angle + 1), 1):
                self.queue.put((self.angle_to_pulse_width(a), t))
        else:
            for a in xrange(int(last_angle), int(angle - 1), -1):
                self.queue.put((self.angle_to_pulse_width(a), t))

        self.last_pulse_width = pulse_width
        self.last_angle = angle

        if not asynchronous:
            self.queue.join()

    def turn_off(self):
        self.pwm.set_enabled(False)

    def stop(self):
        self.running = False
        self.t.join()
        self.turn_off()

    def _wait_for_event(self):
        while self.running:
            try:
                ev = self.queue.get(block=True, timeout=1)
            except Queue.Empty:
                if self.turnoff_timeout > 0 and self.lastCommandTime > 0 and time.time(
                ) - self.lastCommandTime > self.turnoff_timeout:
                    self.lastCommandTime = 0
                    self.turn_off()
                continue
            except Exception:
                # To avoid exception printed on output
                pass

            self.current_pulse_width = ev[0]
            logging.debug("setting pulse width to " +
                          str(self.current_pulse_width))
            self.pwm.set_value(self.current_pulse_width / self.pulse_length)
            self.lastCommandTime = time.time()
            time.sleep(ev[1])

            self.queue.task_done()

    def angle_to_pulse_width(self, angle):
        return (
            (angle - self.angle_min) /
            self.angle_total) * self.pulse_width_total + self.pulse_width_min

    def pulse_width_to_angle(self, pulse_width):
        return (((pulse_width - self.pulse_width_min) /
                 (self.pulse_width_total)) * self.angle_total) + self.angle_min
Example #5
0
class Servo:
    def __init__(self, channel, shiftreg_nr, pulse_width_start, pulse_width_stop, init_angle, turnoff_timeout=0):
        """Define a new software controllable servo with adjustable speed control

        Keyword arguments:
        pulse_width_start -- The minimum pulse width defining the lowest angle
        pulse_width_stop -- The maximum pulse width defining the biggest angle
        init_angle -- Initial angle that the servo should take when it is powered on. Range is 0 to 180deg
        turnoff_timeout -- number of seconds after which the servo is turned off if no command is received. 0 = never turns off
        """

        self.pulse_width_start = pulse_width_start
        self.pulse_width_stop = pulse_width_stop
        self.turnoff_timeout = turnoff_timeout

        self.current_pulse_width = (init_angle*(self.pulse_width_stop-self.pulse_width_start)/180.0+self.pulse_width_start)
        self.last_pulse_width = self.current_pulse_width

        self.queue = JoinableQueue(1000)
        self.lastCommandTime = 0

        self.t = Thread(target=self._wait_for_event)
        self.t.daemon = True
        self.running = True
        self.t.start()

        self.pwm = PWM_pin(channel, 100, 0.1)

        # Set up the Shift register for enabling this servo
        ShiftRegister.make()
        self.shift_reg = ShiftRegister.registers[shiftreg_nr]
        self.set_enabled()

    def set_enabled(self, is_enabled=True):
        if is_enabled:
            self.shift_reg.add_state(0x01)
        else:
            self.shift_reg.remove_state(0x01)


    def set_angle(self, angle, speed=60, asynchronous=True):
        ''' Set the servo angle to the given value, in degree, with the given speed in deg / sec '''
        pulse_width = angle*(self.pulse_width_stop-self.pulse_width_start)/180.0+self.pulse_width_start
        last_angle = (self.last_pulse_width-self.pulse_width_start)/float(self.pulse_width_stop-self.pulse_width_start)*180.0
        
        
        t = (math.fabs(angle-last_angle)/speed) / math.fabs(angle-last_angle)

        for w in xrange(int(self.last_pulse_width*1000), int(pulse_width*1000), (1 if pulse_width>=self.last_pulse_width else -1)):
            self.queue.put((w/1000.0,t))

        self.last_pulse_width = pulse_width
        
        if not asynchronous:
            self.queue.join()

    def turn_off(self):
        self.pwm.set_enabled(False)

    def stop(self):
        self.running = False
        self.t.join()
        self.turn_off()

    def _wait_for_event(self):
        while self.running:
            try:
                ev = self.queue.get(block=True, timeout=1)
            except Queue.Empty:
                if self.turnoff_timeout>0 and self.lastCommandTime>0 and time.time()-self.lastCommandTime>self.turnoff_timeout:
                    self.lastCommandTime = 0
                    self.turn_off()
                continue
            except Exception:
                # To avoid exception printed on output
                pass

            self.current_pulse_width = ev[0]
            self.pwm.set_value(self.current_pulse_width)
            self.lastCommandTime = time.time()
            time.sleep(ev[1])

            self.queue.task_done()
Example #6
0
class Servo:
    def __init__(self,
                 channel,
                 pulse_width_start,
                 pulse_width_stop,
                 init_angle,
                 turnoff_timeout=0):
        """Define a new software controllable servo with adjustable speed control

        Keyword arguments:
        pulse_width_start -- The minimum pulse width defining the lowest angle
        pulse_width_stop -- The maximum pulse width defining the biggest angle
        init_angle -- Initial angle that the servo should take when it is powered on. Range is 0 to 180deg
        turnoff_timeout -- number of seconds after which the servo is turned off if no command is received. 0 = never turns off
        """

        self.pulse_width_start = pulse_width_start
        self.pulse_width_stop = pulse_width_stop
        self.turnoff_timeout = turnoff_timeout

        self.current_pulse_width = init_angle * (
            self.pulse_width_stop -
            self.pulse_width_start) / 180.0 + self.pulse_width_start
        self.last_pulse_width = self.current_pulse_width

        self.queue = JoinableQueue(1000)
        self.lastCommandTime = 0

        self.t = Thread(target=self._wait_for_event)
        self.t.daemon = True
        self.running = True
        self.t.start()

        self.pwm = PWM_pin(channel, 100, self.current_pulse_width)

        # Set up the Shift register for enabling this servo
        if channel == "P9_14":
            shiftreg_nr = 3
        elif channel == "P9_16":
            shiftreg_nr = 2
        else:
            logging.warning(
                "Tried to assign servo to an unknown channel/pin: " +
                str(channel))
            return

        ShiftRegister.make()
        self.shift_reg = ShiftRegister.registers[shiftreg_nr]
        self.set_enabled()

    def set_enabled(self, is_enabled=True):
        if is_enabled:
            self.shift_reg.add_state(0x01)
        else:
            self.shift_reg.remove_state(0x01)

    def set_angle(self, angle, speed=60, asynchronous=True):
        ''' Set the servo angle to the given value, in degree, with the given speed in deg / sec '''
        pulse_width = angle * (self.pulse_width_stop - self.pulse_width_start
                               ) / 180.0 + self.pulse_width_start
        last_angle = (self.last_pulse_width - self.pulse_width_start) / float(
            self.pulse_width_stop - self.pulse_width_start) * 180.0

        t = (math.fabs(angle - last_angle) / speed) / math.fabs(angle -
                                                                last_angle)

        for w in xrange(int(self.last_pulse_width * 1000),
                        int(pulse_width * 1000),
                        (1 if pulse_width >= self.last_pulse_width else -1)):
            self.queue.put((w / 1000.0, t))

        self.last_pulse_width = pulse_width

        if not asynchronous:
            self.queue.join()

    def turn_off(self):
        self.pwm.set_enabled(False)

    def stop(self):
        self.running = False
        self.t.join()
        self.turn_off()

    def _wait_for_event(self):
        while self.running:
            try:
                ev = self.queue.get(block=True, timeout=1)
            except Queue.Empty:
                if self.turnoff_timeout > 0 and self.lastCommandTime > 0 and time.time(
                ) - self.lastCommandTime > self.turnoff_timeout:
                    self.lastCommandTime = 0
                    self.turn_off()
                continue
            except Exception:
                # To avoid exception printed on output
                pass

            self.current_pulse_width = ev[0]
            self.pwm.set_value(self.current_pulse_width)
            self.lastCommandTime = time.time()
            time.sleep(ev[1])

            self.queue.task_done()
Example #7
0
    def __init__(self, channel, pulse_width_min, pulse_width_max, angle_min, angle_max, init_angle, turnoff_timeout=0):
        """Define a new software controllable servo with adjustable speed control

        Keyword arguments:
        pulse_width_min -- The minimum pulse width defining the lowest angle
        pulse_width_max -- The maximum pulse width defining the biggest angle
        init_angle -- Initial angle that the servo should take when it is powered on. Range is 0 to 180deg
        turnoff_timeout -- number of seconds after which the servo is turned off if no command is received. 0 = never turns off
        """

        self.angle_min = angle_min
        self.angle_max = angle_max
        self.angle_total = angle_max-angle_min
        self.pulse_width_min = pulse_width_min
        self.pulse_width_max = pulse_width_max
        self.pulse_width_total = pulse_width_max-pulse_width_min
        
        self.turnoff_timeout = turnoff_timeout

        self.current_pulse_width = self.angle_to_pulse_width(init_angle)
        self.last_pulse_width = self.current_pulse_width

        self.last_angle = init_angle

        self.pulse_length = 20.0*10.0**-3.0 # 20 ms

        logging.debug("Angle min: {} deg".format(self.angle_min))
        logging.debug("Angle max: {} deg".format(self.angle_max))
        logging.debug("Angle tot: {} deg".format(self.angle_total))
        logging.debug("Pulse min: {} ms".format(self.pulse_width_min*1000.0))
        logging.debug("Pulse max: {} ms".format(self.pulse_width_max*1000.0))
        logging.debug("Pulse tot: {} ms".format(self.pulse_width_total*1000.0))

        self.queue = JoinableQueue(1000)
        self.lastCommandTime = 0

        self.t = Thread(target=self._wait_for_event)
        self.t.daemon = True
        self.running = True
        self.t.start()

        # Branch based on channel type.

        if type(channel) == int: # Revision A
            self.pwm = PWM(channel, 50, self.current_pulse_width)
        else: # Revision B
            # Set up the Shift register for enabling this servo
            if channel == "P9_14":
                shiftreg_nr = 1
                self.pwm = PWM_pin(channel, 50, self.current_pulse_width)
            elif channel == "P9_16":
                shiftreg_nr = 2
                self.pwm = PWM_pin(channel, 50, self.current_pulse_width)
            else:
                logging.warning("Tried to assign servo to an unknown channel/pin: "+str(channel))
                return        

            ShiftRegister.make(5)
            self.shift_reg = ShiftRegister.registers[shiftreg_nr]
        self.set_enabled()
        self.pwm.set_value(self.angle_to_pulse_width(init_angle)/self.pulse_length)
Example #8
0
class Servo:
    def __init__(self, channel, pulse_width_min, pulse_width_max, angle_min, angle_max, init_angle, turnoff_timeout=0):
        """Define a new software controllable servo with adjustable speed control

        Keyword arguments:
        pulse_width_min -- The minimum pulse width defining the lowest angle
        pulse_width_max -- The maximum pulse width defining the biggest angle
        init_angle -- Initial angle that the servo should take when it is powered on. Range is 0 to 180deg
        turnoff_timeout -- number of seconds after which the servo is turned off if no command is received. 0 = never turns off
        """

        self.angle_min = angle_min
        self.angle_max = angle_max
        self.angle_total = angle_max-angle_min
        self.pulse_width_min = pulse_width_min
        self.pulse_width_max = pulse_width_max
        self.pulse_width_total = pulse_width_max-pulse_width_min
        
        self.turnoff_timeout = turnoff_timeout

        self.current_pulse_width = self.angle_to_pulse_width(init_angle)
        self.last_pulse_width = self.current_pulse_width

        self.last_angle = init_angle

        self.pulse_length = 20.0*10.0**-3.0 # 20 ms

        logging.debug("Angle min: {} deg".format(self.angle_min))
        logging.debug("Angle max: {} deg".format(self.angle_max))
        logging.debug("Angle tot: {} deg".format(self.angle_total))
        logging.debug("Pulse min: {} ms".format(self.pulse_width_min*1000.0))
        logging.debug("Pulse max: {} ms".format(self.pulse_width_max*1000.0))
        logging.debug("Pulse tot: {} ms".format(self.pulse_width_total*1000.0))

        self.queue = JoinableQueue(1000)
        self.lastCommandTime = 0

        self.t = Thread(target=self._wait_for_event)
        self.t.daemon = True
        self.running = True
        self.t.start()

        # Branch based on channel type.

        if type(channel) == int: # Revision A
            self.pwm = PWM(channel, 50, self.current_pulse_width)
        else: # Revision B
            # Set up the Shift register for enabling this servo
            if channel == "P9_14":
                shiftreg_nr = 1
                self.pwm = PWM_pin(channel, 50, self.current_pulse_width)
            elif channel == "P9_16":
                shiftreg_nr = 2
                self.pwm = PWM_pin(channel, 50, self.current_pulse_width)
            else:
                logging.warning("Tried to assign servo to an unknown channel/pin: "+str(channel))
                return        

            ShiftRegister.make(5)
            self.shift_reg = ShiftRegister.registers[shiftreg_nr]
        self.set_enabled()
        self.pwm.set_value(self.angle_to_pulse_width(init_angle)/self.pulse_length)

    def set_enabled(self, is_enabled=True):
        if is_enabled:
            self.shift_reg.add_state(0x01)
        else:
            self.shift_reg.remove_state(0x01)


    def set_angle(self, angle, speed=60, asynchronous=True):
        ''' Set the servo angle to the given value, in degree, with the given speed in deg / sec '''
        angle = max(min(self.angle_max, angle), self.angle_min)
        pulse_width = self.angle_to_pulse_width(angle)
        last_angle = self.last_angle

        logging.debug("Updating angle from {} (pw={}) to {} (pw={}) ".format(last_angle, self.last_pulse_width, angle, pulse_width))

        if angle == last_angle:
            return
        
        t = (math.fabs(angle-last_angle)/speed) / math.fabs(angle-last_angle)

        

        if angle>=last_angle:
            for a in xrange(int(last_angle), int(angle+1), 1):
                self.queue.put((self.angle_to_pulse_width(a),t))
        else:
            for a in xrange(int(last_angle), int(angle-1), -1):
                self.queue.put((self.angle_to_pulse_width(a),t))
        
        self.last_pulse_width = pulse_width
        self.last_angle = angle
        
        if not asynchronous:
            self.queue.join()

    def turn_off(self):
        self.pwm.set_enabled(False)

    def stop(self):
        self.running = False
        self.t.join()
        self.turn_off()

    def _wait_for_event(self):
        while self.running:
            try:
                ev = self.queue.get(block=True, timeout=1)
            except Queue.Empty:
                if self.turnoff_timeout>0 and self.lastCommandTime>0 and time.time()-self.lastCommandTime>self.turnoff_timeout:
                    self.lastCommandTime = 0
                    self.turn_off()
                continue
            except Exception:
                # To avoid exception printed on output
                pass

            self.current_pulse_width = ev[0]
            logging.debug("setting pulse width to "+str(self.current_pulse_width))
            self.pwm.set_value(self.current_pulse_width/self.pulse_length)
            self.lastCommandTime = time.time()
            time.sleep(ev[1])

            self.queue.task_done()


    def angle_to_pulse_width(self, angle):
        return ((angle-self.angle_min)/self.angle_total)*self.pulse_width_total + self.pulse_width_min

    def pulse_width_to_angle(self, pulse_width):
        return (((pulse_width-self.pulse_width_min)/(self.pulse_width_total))*self.angle_total)+self.angle_min