Strange failure of time.sleep(numSeconds)

I am using your code for performMove() from diddySequence in my program. My Diddy looks around, finds a direction symbol by colour, using cv2.contours, drives up to it and when close enough stops, tries to identify the symbol using cv2.FlannBasedMatcher and if successful (sometimes!) executes a left or right turn.

The code is based on diddyJoyBall but uses v4l2 and cv2.video capture instead of piCamera. The image processing routine runs in a separate thread (only a single thread).

When I run diddySequence the performMove() .........

# Function to perform a general movement
def PerformMove(driveLeft, driveRight, numSeconds):
    # Set the motors running
    PBR.SetMotor1(driveRight * maxPower)
    PBR.SetMotor2(-driveLeft * maxPower)
    # Wait for the time
    time.sleep(numSeconds)
    # Turn the motors off
    PBR.MotorsOff()

.......... function works correctly but when used in my program the motors only turn on momentarily and don't complete the full movement. I have found a work around as follows

# Function to perform a general movement        
def PerformMove(driveLeft, driveRight, numSeconds): # try a while/time statement here?
    global PBR
    now = time.time()
    then = now + numSeconds
    while time.time() < then:
        PBR.SetMotor1(driveRight * maxPower)
        PBR.SetMotor2(-driveLeft * maxPower)
    PBR.MotorsOff()

This works as expected.

I realise that without posting my full code it will be difficult for you to give me a definitive answer but I wondered if you had any thoughts as to why the motors don't run for the duration of the time.sleep(numSeconds) function in my code but they do when the same code is used in diddySequence.

I suspect that my lack of understanding of threading is the problem although the movement functions are defined in the main program but are called from the image processing thread. Any help would be much appreciated.

piborg's picture

There are a few possible explanations why the motors stop before the full delay has passed.

These are the most likely culprits:

  1. The communications failsafe mode is enabled.
    In this mode the PicoBorg Reverse automatically shuts the motors off in the event it does not get any messages from the Raspberry Pi for an interval of 1/4 of a second.
    The giveaway that this is happening is the LED on the PicoBorg Reverse should blink when the failsafe activates.
    The PicoBorg Reverse starts with this mode disabled, but many of our examples enable it.
    It can be turned off by calling PBR.SetCommsFailsafe(False).
  2. Another piece of code is also setting motor speeds.
    This could either be another script is running or a different part of the code.
    It might be worth checking if you are running a different script at startup.
  3. The motor outputs are detecting a fault.
    If there is a fault detected the motor outputs are turned off until the next power level is set.
    There are a number of reasons this might happen, but the most likely is that the battery voltage is too low.

I would suggest running python from the ~/picoborgrev directory and trying the following commands manually with the DiddyBorg placed on top of something so the wheels are off the ground:

import PicoBorgRev
PBR = PicoBorgRev.PicoBorgRev()
PBR.Init()
print PBR.GetCommsFailsafe()
PBR.MotorsOff()
PBR.SetMotor1(0.3)
PBR.SetMotor2(0.4)
# Wait a few seconds at this point
print PBR.GetDriveFault()
print PBR.GetMotor1()
print PBR.GetMotor2()
PBR.MotorsOff()

If things are working normally you should see:

False
False
0.3
0.4

Also the motors should run until the last line and the LED should not flash at any stage.

Subscribe to Comments for &quot;Strange failure of time.sleep(numSeconds)&quot;