【问题标题】:Controlling continuous servo using python in Raspberry Pi,but the continuous servo can't stop在树莓派中使用python控制连续伺服,但连续伺服无法停止
【发布时间】:2017-08-03 15:11:51
【问题描述】:

我正在尝试在 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。看到这个问题Raspberry pi servo doesn't stop,但我仍然不知道如何解决这个问题,我该怎么办?

【问题讨论】:

    标签: python raspberry-pi continuous servo


    【解决方案1】:

    我认为您可能有多个问题 - 例如,您似乎使用整数算术计算占空比。要对此进行测试,请在每个循环中添加 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 的脉冲宽度。重复间隔为 20 毫秒,这些对应于 2.5-12.5%。

    请注意,伺服将有一个大约 1.5 毫秒的小死区,因此它将在可能 1.45-1.55 毫秒的输入脉冲宽度范围内停止,否则很难从中获得精确的零速。

    因此,要停止此伺服,请将脉冲宽度设置为“零”宽度 1.5ms 并让它继续运行,伺服将不会旋转。 while true 没有问题 - 这可以保持经典模拟伺服系统所需的脉冲。该伺服是数字伺服,因此可以具有更快的重复率,因此您可以使用 5ms,例如,这为您提供了更高的脉冲宽度分辨率,范围为 10-50%。而且作为一个数字伺服,它似乎只需要一个脉冲来设置它的速度,你也可以在没有 20ms 重复率的情况下工作,当你想改变速度时只需产生一个脉冲。

    无论如何,回到您的代码,基本上,对于 20 毫秒的重复和 1.5 毫秒的标称宽度,您需要将占空比设置为 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 循环,如果有问题,添加打印,一旦你的循环工作就将打印注释掉。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-25
      • 2017-10-26
      相关资源
      最近更新 更多