我正试图控制一个连续伺服(DF15RSMG)使用蟒蛇在树莓Pi,但连续伺服不能停止。代码如下:

import RPi.GPIO as GPIO
import time
import signal
import atexit

atexit.register(GPIO.cleanup)

GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT, initial=False)
p = GPIO.PWM(17,50) #50HZ
p.start(0)
time.sleep(2)

while(True):
  for i in range(0,181,10):
    p.ChangeDutyCycle(2.5 + 10 * i / 180)
    time.sleep(0.02)
    p.ChangeDutyCycle(0)
    time.sleep(0.2)

  for i in range(181,0,-10):
    p.ChangeDutyCycle(2.5 + 10 * i / 180)
    time.sleep(0.02)
    p.ChangeDutyCycle(0)
    time.sleep(0.2)

上面的代码是SG90伺服的工作,看到这个问题Raspberry pi servo doesn't stop,但我还不知道如何解决这个问题,我应该怎么做?

最佳答案

我认为你可能有很多问题-例如你似乎用整数运算来计算duy循环。要测试这一点,请在每个循环中添加一个print i,i/180, 2.5+10*i/180语句。在我使用的Python2.7中,您请求的占空比以每秒1为单位在循环中跳跃,因为计算10*I/180是使用整数算法进行的。您只需将宽度计算更改为使用例如10.0*i/180-但稍后将详细介绍。
不过,看看你的代码,它似乎只是短暂地将脉宽调制设置为7.5%,因此电机应停止0.2秒。
此外,不需要在每次设置后将占空比设置回0-不确定为什么要这样做。
而0.2秒的速度增量之间等待的时间不多(所以你可能会错过停止的时间段),让它变慢可能会让你更容易看到发生了什么。
最重要的是,对于一个连续运动的伺服系统,它是由脉冲宽度控制的伺服系统的速度,所以当驱动脉冲宽度增加到标称“零”宽度以上时,伺服系统前进的速度更快,而当脉冲宽度减小到比零宽度窄时,后退的速度更快。
因此,计算脉冲宽度w毫秒的伺服速度如下:

speed% = (w-1.5)*100

其中w在0.5到2.5毫秒之间变化。100%前进速度需要2.5毫秒的脉冲宽度,100%后退速度(即-100%)需要0.5毫秒的脉冲宽度。20毫秒的重复间隔对应2.5-12.5%。
注意,伺服将有一个小死区约1.5ms,这样它将停止超过输入脉冲宽度范围可能1.45-1.55ms否则将很难从它得到一个准确的零速度。
所以,要停止这个伺服,将脉冲宽度设置为“零”宽度1.5ms,让它在这个位置运行,伺服就不会旋转。这对while-true来说没有问题——它可以让脉冲保持在经典模拟伺服所需的位置。这个伺服是一个数字伺服,所以可以有更快的重复率,所以你可以使用5毫秒,例如,这给你更多的分辨率,脉冲宽度从10-50%不等。而作为一个数字伺服,它似乎只需要一个脉冲来设定速度,你也可以在没有20毫秒重复率的情况下工作,只要在你想改变速度时产生一个脉冲。
无论如何回到你的代码,基本上,20毫秒重复和1.5毫秒的名义宽度,你需要设置占空比为7.5%,伺服将停止。你的代码应该增加和减少围绕这一点,使伺服来回。
我的参考资料是amazon.co.ukhttps://www.amazon.com/DFRobot-DF15RSMG-Degree-Standard-Servo/dp/B014L5CBBA上的这条信息,这是最热门的搜索结果。
我没有硬件来测试这个,但是像这样的东西应该可以更好地工作,我假设你使用的初始化代码可以工作:
import RPi.GPIO as GPIO
import time
import signal
import atexit

atexit.register(GPIO.cleanup)

GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT, initial=False)
p = GPIO.PWM(17,50) #50HZ
p.start(0)
time.sleep(2)

STEPS=10    # the number of steps either side of nominal
NOMINAL=7.5 # the 'zero' PWM %age
RANGE=1.0   # the maximum variation %age above/below NOMINAL

while(True):
    # loop first over "forward" ramp up/down, then reverse.
    for direction in [+1.0,-1.0]:
        # step from 0 to 100% then back to just above zero
        # (next time round the loop will do the 0)
        for step in list(range(STEPS+1))+list(range(STEPS-1,0,-1)):
            dutycycle = NOMINAL + direction*RANGE*step/STEPS
            print direction, step, dutycycle
            p.ChangeDutyCycle(dutycycle)
            time.sleep(1.0)

最后的注释-如果您想了解更多关于您的代码正在做什么的信息,那么对占空比进行单独计算这一非常简单的步骤允许您添加一个print语句,而无需编写两次计算。TBH这是我不喜欢python非常强大的一行结构(如列表理解)的一个原因:一旦你让它们工作,它们就很好,但是对于初学者来说,当它们不工作时,它们剥夺了你看到里面发生了什么的能力。最好只使用几行代码和一个for循环,如果有问题就添加打印,循环工作后就注释打印出来。
最后的最后一件事——如果你想让伺服停止当你退出你的代码,给它一个脉冲宽度为0,否则它不会停止。要确保伺服获得此脉冲,请在设置后至少休眠20毫秒:
p.ChangeDutyCycle(NOMINAL)
time.sleep(0.1)

10-04 10:47