From 48eef133a1df4be658d91df2ab3a1444233f8b52 Mon Sep 17 00:00:00 2001 From: Andrey Pohilko Date: Wed, 13 Sep 2017 11:38:40 +0300 Subject: [PATCH] Timed motor demo works --- demo.py | 23 ++++++++++---- pylegoboost/__init__.py | 68 +++++++++++++++++++++++++++++++++++----- pylegoboost/comms.py | 6 ++-- pylegoboost/constants.py | 13 +++++++- test.py | 6 ++-- 5 files changed, 96 insertions(+), 20 deletions(-) diff --git a/demo.py b/demo.py index 73962b5..284dc98 100644 --- a/demo.py +++ b/demo.py @@ -2,7 +2,7 @@ import logging import traceback from time import sleep -from pylegoboost import MoveHub, COLORS_MAP +from pylegoboost import MoveHub, COLORS from pylegoboost.comms import DebugServerConnection, BLEConnection log = logging.getLogger("demo") @@ -10,19 +10,31 @@ log = logging.getLogger("demo") def demo_all(conn): movehub = MoveHub(conn) - - demo_led_colors(movehub) + # demo_led_colors(movehub) + demo_motors_timed(movehub) def demo_led_colors(movehub): # LED colors demo log.info("LED colors demo") - for color in COLORS_MAP.keys(): - log.info("Setting LED color to: %s", COLORS_MAP[color]) + for color in COLORS.keys(): + log.info("Setting LED color to: %s", COLORS[color]) movehub.led.set_color(color) sleep(1) +def demo_motors_timed(movehub): + log.info("Motors movement demo: timed") + for level in range(0, 101, 5): + level /= 100.0 + log.info("Speed level: %s%%", level) + movehub.motor_A.timed(0.2, level) + movehub.motor_B.timed(0.2, -level) + movehub.motor_AB.timed(1.5, -0.2, 0.2) + movehub.motor_AB.timed(0.5, 1) + movehub.motor_AB.timed(0.5, -1) + + if __name__ == '__main__': logging.basicConfig(level=logging.INFO) @@ -33,4 +45,3 @@ if __name__ == '__main__': connection = BLEConnection().connect() demo_all(connection) - sleep(10) diff --git a/pylegoboost/__init__.py b/pylegoboost/__init__.py index 9ca0157..39c91f3 100644 --- a/pylegoboost/__init__.py +++ b/pylegoboost/__init__.py @@ -1,3 +1,6 @@ +import struct +import time + from pylegoboost.constants import * @@ -11,9 +14,9 @@ class MoveHub(object): self.connection = connection self.led = LED(self) - # self.motor_a - # self.motor_b - # self.motor_ab + self.motor_A = EncodedMotor(self, PORT_A) + self.motor_B = EncodedMotor(self, PORT_B) + self.motor_AB = EncodedMotor(self, PORT_AB) # self.port_c # self.port_d @@ -37,16 +40,67 @@ class Peripheral(object): class LED(Peripheral): def set_color(self, color): - if color not in COLORS_MAP: + if color not in COLORS: raise ValueError("Color %s is not in list of available colors" % color) cmd = CMD_SET_COLOR + chr(color) self.parent.connection.write(MOVE_HUB_HARDWARE_HANDLE, cmd) -class InteractiveMotor(object): - pass +class EncodedMotor(Peripheral): + PACKET_VER = b'\x01' + SET_PORT_VAL = b'\x81' + MOTOR_TIMED_END = b'\x64\x7f\x03' + TRAILER = b'\x64\x7f\x03' # NOTE: \x64 is 100, might mean something + TIMED_GROUP = b'\x0A' + TIMED_SINGLE = b'\x09' + MOVEMENT_TYPE = b'\x11' + + def __init__(self, parent, port): + super(EncodedMotor, self).__init__(parent) + if port not in PORTS: + raise ValueError("Invalid port for motor: %s" % port) + self.port = port + + def _speed_abs(self, relative): + relative *= 100 + if relative < 0: + relative += 255 + return int(relative) + + def timed(self, seconds, speed_primary=1, speed_secondary=None, async=False): + if speed_primary < -1 or speed_primary > 1: + raise ValueError("Invalid primary motor speed value: %s", speed_primary) + + if speed_secondary is None: + speed_secondary = speed_primary + + if speed_secondary < -1 or speed_secondary > 1: + raise ValueError("Invalid secondary motor speed value: %s", speed_primary) + + time_ms = int(seconds * 1000) + + # set for port + command = self.SET_PORT_VAL + chr(self.port) + + # movement type + command += self.MOVEMENT_TYPE + command += self.TIMED_GROUP if self.port == PORT_AB else self.TIMED_SINGLE + + command += struct.pack('