0

I have a few micro servo motors connected to a PCA9685 board and I require them to make a small and fast rotation (as fast as the servo motors allow me) every now and then.

I am new to servos and although I understand how the duty cycle works I do not completely understand the intricacies of the behavior of the library, especially with Python.

The code I have right now follows:

from time import sleep
from adafruit_servokit import ServoKit

pca = ServoKit(channels=16)
pca.servo[0].set_pulse_width_range(600,2560) # calibration

def tick():
    dt = 0.1
    pca.servo[0].angle = 40
    sleep(dt)
    pca.servo[0].angle = 0
    sleep(5)
    pca.servo[0].angle = 40
    sleep(dt)
    pca.servo[0].angle = 0
    sleep(dt)

tick()

Here what I expect when I call tick() is the servo motor to first go to 40º and back to 0º ideally with no delay, and do it again after 5 seconds. This does work, but it's not as accurate as I would like it to be. I want the time spent in sleep(dt) as small as possible (less than 10 milliseconds if possible), but If I lower the value the servo motor will not reach the desired angle in time.

The specification of this motor says they have an angular velocity of around 60º/0.12s = 500 degrees/s although this one seems to be lower, around 400 degrees/s. This is where I got the value dt = 40 degrees divided by 400 degrees/s = 0.1s so I need to give the servo motor time to reach the angle, but I could be 100% wrong (does it even make sense to compute this?).

I am not fully understanding what needs to be done here. Is there a way to turn this code into a synchronous task, so that the servo goes to 40 and back to 0 without the need to time it? Why is sleep() even needed at all to perform this?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
ZoiloN
  • 1
  • 2
  • I guess I don't understand part of your question: a delay of some sort is necessary to give the servo enough time to reach the new position. If you don't delay long enough and change the signal to indicate a new position before it's completed the previous move, then it's simply going to start moving to the new position. That's why `sleep()` is necesasry; the motor doesn't have any logic that says, "don't start processing a new position until you reach the previously requested one". – larsks Aug 23 '23 at 18:52
  • 1
    And furthermore hobby servos don't give any kind of position feedback to your microcontroller, so you can't just wait for them to reach the target position. Servo pulses are typically sent every 20 ms, so if you're sleeping for 100 ms, that is about 5 pulses. You might benefit from creating or using a library that gives you more control over exactly what pulses are sent and how many times they are sent, and at what times. – David Grayson Aug 23 '23 at 18:57
  • You're not thinking in real time. `pca.servo[0].angle = 40` sends a command and returns immediately, with the servo still moving. If you send another command immediately, that aborts the shift to 40 and sets a new target. My guess is if you change `dt` to 0.2, you'd see it get to fully to 40 degrees. 100ms of that would be moving, 100ms would be delay. – Tim Roberts Aug 23 '23 at 19:01
  • python interpreter does not provide any sort of real-time performance needed to control fast moving servos, you never know really how long sleep() will actually execute – maciek Aug 24 '23 at 08:12

0 Answers0