~ni/nxt-python

6f83ad4ef0314da888cb582a30ce1c916409bf47 — marvin 3 months ago d8d5ad2
Add possibility to stop motor.turn()
2 files changed, 47 insertions(+), 10 deletions(-)

A examples/tutorial/stop_turning_motor.py
M nxt/motor.py
A examples/tutorial/stop_turning_motor.py => examples/tutorial/stop_turning_motor.py +27 -0
@@ 0,0 1,27 @@
#!/usr/bin/python3
import nxt.locator
import nxt.motor

import time
import threading

with nxt.locator.find() as b:
    # Get the motor connected to the port A.
    mymotor: nxt.motor.BaseMotor = b.get_motor(nxt.motor.Port.A)

    stop_motor = False  # controls wether the motor should stop turning

    # create thread that turns the motor
    t = threading.Thread(target=mymotor.turn, kwargs={
                         'power': 50, 'tacho_units': 360*4, 'brake': True, 'stop_turn': lambda: stop_motor})
    t.start()

    # stop motor after 1sec (motor would turn approximately 3sec)
    time.sleep(1)
    stop_motor = True

    t.join()

    # release motor after 1sec since brake=True
    time.sleep(1)
    mymotor.idle()

M nxt/motor.py => nxt/motor.py +20 -10
@@ 197,7 197,7 @@ def get_tacho_and_state(values):
class BaseMotor:
    """Base class for motors"""

    def turn(self, power, tacho_units, brake=True, timeout=1, emulate=True):
    def turn(self, power, tacho_units, brake=True, timeout=1, emulate=True, stop_turn=lambda: False):
        """Use this to turn a motor.

        :param int power: Value between -127 and 128 (an absolute value greater than 64


@@ 212,9 212,11 @@ class BaseMotor:
           If ``True``, a run() function equivalent is used. Warning: motors remember
           their positions and not using emulate may lead to strange behavior,
           especially with synced motors
        :param lambda: bool stop_turn: If stop_turn returns ``True`` the motor stops turning. 
           Depending on ``brake`` it stops by holding or not holding the motor.

        The motor will not stop until it turns the desired distance. Accuracy is much
        better over a USB connection than with bluetooth...
        The motor will not stop until it turns the desired distance or stop_turn is set to True. 
        Accuracy is much better over a USB connection than with bluetooth...
        """

        tacho_limit = tacho_units


@@ 246,20 248,25 @@ class BaseMotor:

        direction = 1 if power > 0 else -1
        logger.debug("tachocount: %s", tacho)

        current_time = time.time()
        last_time = time.time()
        tacho_target = tacho.get_target(tacho_limit, direction)

        blocked = False
        sleep_time = self._eta(tacho, tacho_target, power) / 2

        try:
            while True:
                time.sleep(self._eta(tacho, tacho_target, power) / 2)
            while not stop_turn():
                current_time = time.time()

                if not blocked:  # if still blocked, don't reset the counter
                    last_tacho = tacho
                    last_time = current_time
                if current_time - last_time < sleep_time:
                    continue
                else:
                    if not blocked:  # if still blocked, don't reset the counter
                        last_tacho = tacho
                        last_time = current_time

                tacho = self.get_tacho()
                current_time = time.time()
                blocked = self._is_blocked(tacho, last_tacho, direction)
                if blocked:
                    logger.debug("not advancing: %s %s", last_tacho, tacho)


@@ 272,10 279,13 @@ class BaseMotor:
                            raise BlockedException("Blocked!")
                else:
                    logger.debug("advancing: %s %s", last_tacho, tacho)

                if tacho.is_near(tacho_target, threshold) or tacho.is_greater(
                    tacho_target, direction
                ):
                    break

                sleep_time = self._eta(tacho, tacho_target, power) / 2
        finally:
            if brake:
                self.brake()