在树莓派中使用python控制连续舵机,但连续舵机停不下来

问题描述 投票:0回答:2

我试图在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伺服器。看到这个问题Raspberry pi伺服器不停止,但我仍然不知道如何解决这个问题,我该怎么办?

python raspberry-pi continuous servo
2个回答
2
投票

我认为您可能有多个问题 - 例如您似乎使用整数算术来计算占空比。要测试这一点,请在每个循环中添加一个

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.5ms 的小死区,以便它会在可能 1.45-1.55ms 的输入脉冲宽度范围内停止,否则很难从中获得精确的零速度。

因此,要停止该舵机,请将脉冲宽度设置为“零”宽度 1.5ms 并让它继续运行,舵机将不会旋转。没有问题,而 true - 这使脉冲保持经典模拟伺服系统所需的位置。该伺服系统是数字伺服系统,因此可以具有更快的重复率,因此您可以使用 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)  

最后的评论 - 如果您想了解有关代码正在做什么的更多信息,单独计算占空比的非常简单的步骤允许您添加打印语句,而无需编写两次计算。说实话,这就是我不太喜欢 Python 非常强大的单行结构(例如列表推导)的原因:一旦你让它们工作,它们就很棒,但对于初学者来说,当它们不起作用时,它们会剥夺你的能力看看里面发生了什么。更好的方法是简单地使用更多行代码和一个 for 循环,如果出现问题则添加打印,在循环工作后对打印进行注释。

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

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

0
投票

花几个小时来理解问题:

  • 网上大部分教程都关注SG90,是伺服控制角度比例的
  • 我的舵机是FS90R,一模一样,除了参考之外没有任何外部区别,那就是连续舵机。很难在给定的角度位置获得相同的行为:它是为了运行机器人或风扇而设计的!
© www.soinside.com 2019 - 2024. All rights reserved.