在Raspberry Pi中使用python控制连续伺服,但连续伺服无法停止

时间:2017-08-03 15:11:52

标签: python raspberry-pi continuous servo

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

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,但我仍然不知道如何解决这个问题,我该怎么办?

1 个答案:

答案 0 :(得分:2)

我认为您可能有多个问题 - 例如,您似乎使用整数运算来计算duy循环。要对此进行测试,请在每个循环中添加print i,i/180, 2.5+10*i/180语句。使用我正在使用的python 2.7,你请求的占空比每秒循环以1为单位跳转,因为计算10 * i / 180是使用整数运算。您所要做的就是更改宽度计算以使用例如10.0 * i / 180 - 但稍后会更多。

然而,看一下你的代码,看起来确实将PWM设置为7.5%,因此电机应停止0.2秒。

每次设置后也无需将占空比设置为0 - 不确定为什么这样做。

并且在速度增量之间等待的时间不超过0.2秒(因此您可能会错过停止的时间段),使速度变慢可能会让您更容易看到正在发生的事情。

最重要的是,对于连续运动伺服,伺服的速度由脉冲宽度控制 - 因此当驱动脉冲宽度增加到标称“零”宽度以上时,伺服“向前”变得更快,并且更快向后,因为脉冲宽度比零宽度窄。

因此,脉冲宽度为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 final thing - 如果你想在退出代码时停止伺服,给它一个零宽度1.5ms的脉冲,否则它不会停止。为确保伺服电机在设置后至少保持20分钟的休眠状态:

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