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)