2017-08-03 55 views
2

我试图用树莓派中的python控制连续伺服(DF15RSMG),但连续伺服无法停止。代码如下:在Raspberry Pi中使用python控制连续伺服,但连续伺服不能停止

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 Servo.Having工作看到了这个问题Raspberry pi servo doesn't stop,但我仍然不知道如何解决这个问题,我该怎么办?

回答

2

我认为你可能有多个问题 - 例如你似乎用整数算术计算duy循环。要测试它,请在每个循环中添加一个print i,i/180, 2.5+10*i/180语句。使用我正在使用的python 2.7,因为计算10 * i/180是使用整数算术计算的,所以您请求的占空比以循环每隔1秒为单位跳过一次。您只需更改宽度计算即可使用10.0 * i/180 - 但稍后更多。

然而看着你的代码,它似乎简单地将PWM设置为7.5%,所以电机应该停止0.2秒。

也不需要在每次设置后将占空比设置回0 - 不知道为什么你这样做。

0.2s在速度增量之间等待的时间并不多(因此您可能会错过停止的时间段),使其变慢可能会更容易看出发生了什么。

最重要的是,对于连续运动伺服,它是由脉冲宽度控制的伺服的速度 - 所以当驱动脉冲宽度增加到高于标称“零”宽度时,伺服更快地“前进”,并且随着脉冲宽度的减小比零宽度更窄,反向更快。

所以伺服用于脉冲宽度w毫秒的速度被计算是这样的:

speed% = (w-1.5)*100 

其中w变化毫秒0.5和2.5之间。 100%前进速度需要2.5ms的脉冲宽度,100%反向(即-100%)速度需要0.5ms的脉冲宽度。以20ms的重复间隔,这些对应于2.5-12.5%。

请注意,伺服将在1.5ms左右有一个小的死区,以便它可能会停止在1.45-1.55ms的输入脉冲宽度范围内,否则很难从中获得精确的零速度。

因此,要停止伺服,请将脉冲宽度设置为“零”宽度1.5ms,并保持该状态,伺服将不会旋转。正确的时候没有问题 - 保持传统模拟伺服所需的脉冲数量。这个伺服是一个数字伺服,因此可以有更快的重复频率,所以你可以使用5ms,例如,它可以使脉冲宽度的分辨率从10-50%变化。作为一个数字伺服器,它似乎只需要一个脉冲来设置它的速度,你也可以在没有20ms重复频率的情况下工作,当你想改变速度时只产生一个脉冲。

无论如何,回到您的代码,基本上,对于20ms的重复和1.5ms的标称宽度,您需要将占空比设置为7.5%,伺服将停止。你的代码应该增加和减少这个,以使伺服反向和前进。

我的参考资料是amazon.co.uk上的这个信息https://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) 

最后的意见 - 如果你想了解更多关于你的代码在做什么,分开计算占空比的非常简单的步骤允许你添加一个打印语句,而不用两次写入计算。 TBH这是一个原因,我不是Python的非常强大的单线程结构如列表理解的忠实粉丝:一旦你让他们工作,他们是伟大的,但对于初学者他们不工作时,他们抢夺你的能力看看里面发生了什么。更好的方法是简单地使用更多的代码行和for循环,如果出现问题则添加打印,并在循环运行后评论打印输出。

FINAL最后一件事 - 如果您希望伺服器在您退出代码时停止,请给它一个零宽度为1.5ms的脉冲,否则它不会停止。为确保伺服器获得此脉冲,在设置后至少进行20ms的睡眠:

p.ChangeDutyCycle(NOMINAL) 
time.sleep(0.1)