Mercurial > Kubik
changeset 135:21f3cbb3839b
bundle the maestro lib
| author | Radomir Dopieralski <sheep-devel@sheep.art.pl> |
|---|---|
| date | Tue, 15 Jul 2014 00:51:31 +0200 |
| parents | 2607d82685d2 |
| children | 14087ba87a99 |
| files | maestro.py |
| diffstat | 1 files changed, 120 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/maestro.py Tue Jul 15 00:51:31 2014 +0200 @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +A simple library for talking to the Pololu Maestro RC servo controllers. +""" + +import logging + + +LOG = logging.getLogger(__name__) + + +class Maestro(object): + def __init__(self, serial): + self.serial = serial + + def _write(self, values): + LOG.debug('Writing %s' % ' '.join(hex(v) for v in values)) + self.serial.write(''.join(chr(v) for v in values)) + + def _write_command(self, command): + self._write([int(command) | 128]) + + def _write_byte(self, byte): + self._write([int(byte) & 127]) + + def _write_word(self, word): + byte2, byte1 = divmod(int(word), 128) + self._write([byte1 & 127, byte2 & 127]) + + def _read(self, count): + values = [ord(c) for c in self.serial.read(count)] + LOG.debug('Reading %s' % ' '.join(hex(v) for v in values)) + return values + + def _read_byte(self): + return self._read(1)[0] + + def _read_word(self): + byte1, byte2 = self._read(2) + return byte1 + byte2 * 256 + + def init(self): + """Initialize the communication.""" + self._write_command(0xAA) + + def set_target(self, servo, target): + """Set the servo position, in 1/4 of milliseconds of pulse width.""" + self._write_command(0x84) + self._write_byte(servo) + self._write_word(target) + + def set_speed(self, servo, speed): + """Set the servo speed limit.""" + self._write_command(0x87) + self._write_byte(servo) + self._write_word(speed) + + def set_accel(self, servo, accel): + """Set the servo acceleration limit.""" + self._write_command(0x89) + self._write_byte(servo) + self._write_word(accel) + + def get_position(self, servo): + """Read the current position of a servo.""" + self._write_command(0x90) + self._write_byte(servo) + return self._read_word() + + def get_moving_state(self): + """True if any servo is still moving, otherwise False.""" + self._write_command(0x93) + return bool(self._read_byte()) + + +class Servo(object): + min_position = 3968 + max_position = 8064 + max_degrees = 90 + + def __init__(self, maestro, index, center=None, + reverse=False, trim=0): + self.maestro = maestro + self.index = index + self.reverse = reverse + self.width = self.max_position - self.min_position + if center is None: + self.center = self.min_position + self.width / 2 + else: + self.center = center + self.trim = trim + + def move_degrees(self, degrees): + self._angle = degrees + position = (self.width * degrees) / self.max_degrees + if self.reverse: + position = -position + target = self.center + position + self.trim + target = min(self.max_position, max(self.min_position, target)) + self.maestro.set_target(self.index, target) + + def set_speed(self, degrees_per_milisecond): + speed = (self.width * degrees_per_milisecond) / self.max_degrees + self.maestro.set_speed(self.index, speed) + + def set_accel(self, accel): + self.maestro.set_accel(self.index, accel) + + def get_degrees(self): + target = self.get_position(self.index) + position = target - self.center - self.trim + if self.reverse: + position = -position + return (self.max_degrees * position) / self.width + + def stop(self): + target = self.get_position(self.index) + self.maestro.set_target(self.index, target)
