在Raspberry Pi中使用python控制连续伺服,但是连续伺服不能停止
Controlling continuous servo using python in Raspberry Pi,but the continuous servo can't stop
我正在尝试使用 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 看到这个问题 ,但我仍然不知道如何解决这个问题,我该怎么办?
我认为您可能有多个问题 - 例如,您似乎使用整数运算来计算占空比。要对此进行测试,请在每个循环中添加一个 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 秒在速度增量之间等待的时间不多(因此您可能会错过停止时间),使其变慢可能会更容易看到正在发生的事情。
最重要的是,对于连续运动伺服来说,伺服的速度是由脉冲宽度控制的——所以当驱动脉冲宽度增加到标称值以上时,伺服'forwards'的速度会更快'zero' 宽度,并且随着脉冲宽度减小到比零宽度更窄,向后更快。
所以脉宽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 的输入脉冲宽度范围内,否则很难从中获得精确的零速度。
因此,要停止此舵机,请将脉冲宽度设置为 'zero' 宽度 1.5ms 并保持 运行 不变,舵机将不会旋转。 while 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 循环要好得多,如果有问题就添加打印,一旦你的循环工作就注释掉打印。
FINAL 最后一件事——如果你想让伺服在你退出代码时停止,给它一个零宽度1.5ms的脉冲,否则它不会停止。为确保伺服获得此脉冲,请在设置后至少休眠 20 毫秒:
p.ChangeDutyCycle(NOMINAL)
time.sleep(0.1)
我正在尝试使用 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 看到这个问题
我认为您可能有多个问题 - 例如,您似乎使用整数运算来计算占空比。要对此进行测试,请在每个循环中添加一个 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 秒在速度增量之间等待的时间不多(因此您可能会错过停止时间),使其变慢可能会更容易看到正在发生的事情。
最重要的是,对于连续运动伺服来说,伺服的速度是由脉冲宽度控制的——所以当驱动脉冲宽度增加到标称值以上时,伺服'forwards'的速度会更快'zero' 宽度,并且随着脉冲宽度减小到比零宽度更窄,向后更快。
所以脉宽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 的输入脉冲宽度范围内,否则很难从中获得精确的零速度。
因此,要停止此舵机,请将脉冲宽度设置为 'zero' 宽度 1.5ms 并保持 运行 不变,舵机将不会旋转。 while 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 循环要好得多,如果有问题就添加打印,一旦你的循环工作就注释掉打印。
FINAL 最后一件事——如果你想让伺服在你退出代码时停止,给它一个零宽度1.5ms的脉冲,否则它不会停止。为确保伺服获得此脉冲,请在设置后至少休眠 20 毫秒:
p.ChangeDutyCycle(NOMINAL)
time.sleep(0.1)