简体   繁体   English

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

[英]Controlling continuous servo using python in Raspberry Pi,but the continuous servo can't stop

I'm trying to control a continuous servo(DF15RSMG) using python in Raspberry Pi, but the continuous servo can't stop. 我试图在Raspberry Pi中使用python控制连续伺服(DF15RSMG),但连续伺服不能停止。 Code as follows: 代码如下:

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)  

Code above is work for SG90 Servo.Having seen this question Raspberry pi servo doesn't stop ,but I still haven't know how to solve this problem,What should I do? 上面的代码是SG90 伺服的工作。看到这个问题Raspberry pi伺服不停 ,但我还是不知道如何解决这个问题,我该怎么办?

I think you may have multiple problems - for example you appear to calculate the duy cycle using integer arithmetic. 我认为你可能有多个问题 - 例如你似乎使用整数运算来计算duy循环。 To test this, add a print i,i/180, 2.5+10*i/180 statement in each loop. 要测试这一点,请在每个循环中添加print i,i/180, 2.5+10*i/180语句。 With python 2.7 that I am using, the duty cycle you are requesting jumps in units of 1 every second time round the loop because the calculation 10*i/180 is made using integer arithmetic. 使用我正在使用的python 2.7,你请求的占空比每秒循环以1为单位跳转,因为计算10 * i / 180是使用整数运算。 All you have to do is change the width calculation to use eg 10.0*i/180 - but more on that later. 您所要做的就是将宽度计算更改为使用例如10.0 * i / 180 - 但稍后会更多。

However looking at your code it does appear to briefly set the PWM to 7.5% so the motor should stop for 0.2s. 但是看一下你的代码,看起来确实将PWM设置为7.5%,因此电机应该停止0.2秒。

Also there is no need to set the duty cycle back to 0 after each setting - not sure why you do that. 此外,无需在每次设置后将占空比设置回0 - 不确定为什么这样做。

And 0.2s isn't much time to wait between speed increments (so you may be missing the stopped period), make it slower might make it easier to see what is going on. 并且0.2s在速度增量之间等待的时间不多(因此您可能会错过停止的时间段),使速度变慢可能会让您更容易看到正在发生的事情。

Most importantly, for a continuous movement servo it is the speed of the servo which is controlled by the pulse width - so the servo goes 'forwards' faster as the drive pulse width increases above the nominal 'zero' width, and faster backwards as the pulse width reduces narrower than the zero width. 最重要的是,对于连续运动伺服,伺服的速度由脉冲宽度控制 - 因此当驱动脉冲宽度增加到标称“零”宽度以上时伺服“向前”更快,并且向后更快。脉冲宽度比零宽度窄。

So the speed of the servo for a pulse width w milliseconds is calculated something like: 因此,脉冲宽度为w毫秒的伺服速度计算如下:

speed% = (w-1.5)*100

where w varies between 0.5 and 2.5 milliseconds. 其中w在0.5到2.5毫秒之间变化。 100% forward speed needs a pulse width of 2.5ms, and 100% reverse (ie -100%) speed needs a pulse width of 0.5ms. 100%正向速度需要2.5ms的脉冲宽度,100%反向(即-100%)速度需要0.5ms的脉冲宽度。 With a repeat interval of 20ms these correspond to 2.5-12.5%. 重复间隔为20ms,这相当于2.5-12.5%。

NOTE that the servo will have a small dead band around 1.5ms so that it will stop over input pulse width range of perhaps 1.45-1.55ms otherwise it would be very difficult to get an exact zero speed from it. 请注意,伺服器具有1.5ms左右的小死区,因此它将在大约1.45-1.55ms的输入脉冲宽度范围内停止,否则很难从中获得精确的零速度。

So, to stop this servo, set the pulse width to the 'zero' width 1.5ms and leave it running at that, and the servo will not rotate. 因此,要停止此伺服,请将脉冲宽度设置为“零”宽度1.5ms并使其保持运行,伺服不会旋转。 No problem with the while true - that keeps the pulses going which where needed for classic analogue servos. 没有问题的同时真实 - 保持脉冲在经典模拟伺服系统所需的位置。 This servo is a digital servo so can have faster repetition rate so you could use 5ms, for example, which gives you more resolution of the pulse width varying from 10-50%. 这种伺服是一种数字伺服,因此可以具有更快的重复率,因此您可以使用5ms,例如,这使您可以获得更高的脉冲宽度分辨率,从10-50%变化。 And as a digital servo it appears to only need a single pulse to set its speed, you could also work without the 20ms repeat rate, just generate a pulse when you want to change the speed. 而作为数字伺服系统,它似乎只需要一个脉冲来设置其速度,您也可以在没有20ms重复速率的情况下工作,只需在您想要改变速度时产生脉冲。

Anyway back to your code, basically, for 20ms repetitions and nominal width of 1.5ms, you need to set the duty cycle to 7.5% and the servo will stop. 无论如何回到你的代码,基本上,重复20ms,标称宽度为1.5ms,你需要将占空比设置为7.5%,伺服将停止。 Your code should increase and reduce around this to make the servo go backwards and forwards. 你的代码应该在这周围增加和减少,以使伺服前进和后退。

My reference is this info on amazon.co.uk https://www.amazon.com/DFRobot-DF15RSMG-Degree-Standard-Servo/dp/B014L5CBBA which was the top search result. 我的参考资料是amazon.co.uk上的这些信息https://www.amazon.com/DFRobot-DF15RSMG-Degree-Standard-Servo/dp/B014L5CBBA这是最热门的搜索结果。

I haven't the hardware to test this, but something like this should work better, I'm assuming the initialization code you use works: 我没有硬件来测试这个,但是这样的东西应该更好用,我假设你使用的初始化代码有效:

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)  

Final comment - if you want to find out more about what your code is doing, the very simple step of doing separate calculation of the duty cycle allows you to add a print statement without writing the calculation twice. 最后的注释 - 如果你想了解更多关于你的代码正在做什么的事情,那么单独计算占空比的非常简单的步骤允许你添加一个print语句,而无需编写两次计算。 TBH this is a reason I'm not a great fan of python's very powerful one-liner constructs like list comprehensions: they're great once you get them working, but for beginners when they don't work they rob you of the ability to see what's happening inside. TBH这是一个原因我不是很喜欢python非常强大的单行结构,比如列表理解:一旦你让它们工作就很好,但对于初学者来说,当他们不工作时,他们就会剥夺你的能力看看里面发生了什么。 Far better to simply use a few more lines of code and a for loop, adding prints if there's a problem, commenting the prints out once your loop is working. 最好只使用几行代码和for循环,在出现问题时添加打印件,在循环工作后对打印件进行注释。

FINAL final thing - if you want the servo to stop when you exit your code, give it a pulse of the zero width 1.5ms, otherwise it won't stop. 最后的决定 - 如果你想在退出代码时停止伺服,给它一个零宽度1.5ms的脉冲,否则它不会停止。 To make sure the servo gets this pulse do a sleep for at least 20ms after setting it: 为确保伺服电机在设置后至少保持20分钟的休眠状态:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM