Continious rotation Servo control?

Forums:

Hi,

I got a continious rotation servo https://shop.pimoroni.com/products/micro-360-degree-continuous-rotation-... and replaced the downward facing servo on my Pan-Tilt Hat. I want this to move about -135 degress to + 135 degrees. Anyway to do this via Ultraborg.

The one time I tried, it tried to spin forever and I had to unplug the servo in a hurry.

Thanks
Sumit.

Okay, got it working... kind of...

#!/usr/bin/env python3
# coding: latin-1

# Original Source: https://piborg.org

# Import the libraries we need
import UltraBorg3
import time

# Settings
startupDelay = 0.5              # Delay before making the initial move
pulseWidth = 0.01
rateServo4 = 0.20               # Step distance for servo #4

# Start the UltraBorg
UB = UltraBorg3.UltraBorg()      # Create a new UltraBorg object
UB.Init()                       # Set the board up (checks the board is connected)

try:
    print('Move to central')
    # Initial settings
    servo1 = 0.0
    # Set our initial servo positions
    position = UB.GetServoStartup2()
    print(position)
    UB.SetServoPosition1(servo1)
    # UB.SetServoPosition2(0.0015)
    # Wait a while to be sure the servos have caught up
    time.sleep(startupDelay)
    n = 0
    while n < 20:
        n = n + 1
        UB.SetServoPosition2(rateServo4)
        # Wait until the next step
        time.sleep(pulseWidth)

    UB.SetServoPosition2(0)

except KeyboardInterrupt:
    # User has pressed CTRL+C
    UB.SetServoPosition2(0)

    print('Done')

Problems with this are:
1. I have to depend on Python's timer which isn't the greatest. Does Ultraborg have a usable timer API?
2. I will never know the center position, but I think that's an issue with all cheap continuous rotation servos?

Anyone knows a reliable way to convert pulseWidth to degrees of rotation it will help.
Any suggestions welcome.

Thanks again.
Sumit.

piborg's picture

As you have already found out, continuous servos behave more like DC motors than normal servos. This means when you set your power level (rateServo4) you are actually setting the speed at which it will rotate instead of a position.

While UltraBorg does not have a timer you can use, I have two suggestions that may be helpful here:

  1. With your current code the servo movement includes the time to send the servo position many times, which vary in how long they take. This can be removed by setting the servo rate once, waiting for the whole move time, then setting it back to 0.
  2. You can use a technique known as busy waiting instead of time.sleep to get a more accurate delay. This works by reading the exact time, then continually checking until enough time has passed. The downside is that it will increase the CPU usage of the script and probably increase power usage slightly as well.

Here is the same code as before with these two changes:

#!/usr/bin/env python3
# coding: latin-1

# Original Source: https://piborg.org

# Import the libraries we need
import UltraBorg3
import time

# Settings
startupDelay = 0.5              # Delay before making the initial move
pulseWidth = 0.01
rateServo4 = 0.20               # Step distance for servo #4

# Start the UltraBorg
UB = UltraBorg3.UltraBorg()      # Create a new UltraBorg object
UB.Init()                       # Set the board up (checks the board is connected)

# Function to perform a more accurate delay, but it is
# less power efficient than using time.sleep
def BusyWait(seconds):
    startTime = time.time()
    while (time.time() - startTime) < seconds:
        pass

try:
    print('Move to central')
    # Initial settings
    servo1 = 0.0
    # Set our initial servo positions
    position = UB.GetServoStartup2()
    print(position)
    UB.SetServoPosition1(servo1)
    # UB.SetServoPosition2(0.0015)
    # Wait a while to be sure the servos have caught up
    time.sleep(startupDelay)
    # Move the servo using a single start and stop command
    n = 20
    UB.SetServoPosition2(rateServo4)
    BusyWait(n * pulseWidth)
    UB.SetServoPosition2(0)

except KeyboardInterrupt:
    # User has pressed CTRL+C
    UB.SetServoPosition2(0)

    print('Done')

You may find that your pulseWidth or n value need to be adjusted again as the delay will likely be shorter than it was before.

You are correct that typically continuous servos provide no way of knowing where you currently are. What you can do is add a switch which is pressed when the servo is at one end of the movement you want. This way you can slowly move the servo until the switch is pressed, at which point you know where it is :)

Unfortunately the exact movement from the servo for a power level and time will vary, so it is hard to figure it out without experimenting. As the speed may not be linear with the power level I would suggest sticking with a constant power level that the servo is moved at and changing the delay. This way doubling the delay should also double the angle moved. All you then need to do is experiment to figure out how long is needed for a bigger move, say 90 degrees, and work out what the delay for a single degree is from that.

Hi PiBorg team,

Thank you for your help you folks are awesome. It is great to learn from the masters.

I will definitely expand this answer into a full blog post on how to use a continuous servo for limited rotation. However, at the moment I am in a rush to get my Bot done for PiWars. So I have ordered a 270 degree servo which to do the job when paired with Ultraborg.

This is turning out to be an awesome learning journey.

Thanks again,
Sumit.

Subscribe to Comments for &quot;Continious rotation Servo control?&quot;