查看: 7063|回复: 1

[教程] 基于树莓派的多舵机控制的定位拍照云台

[复制链接]
  • TA的每日心情

    2020-3-6 09:52
  • 签到天数: 13 天

    连续签到: 1 天

    [LV.3]偶尔看看II

    发表于 2018-9-20 14:10:51 | 显示全部楼层 |阅读模式
    分享到:
    1.jpg

    MAKER:mjrovai/译:Cherry(转载请注明出处)
    在本教程中,我们将探讨如何在树莓派上使用Python控制多个舵机。 我们的目标是制作一个支持多自由度定位拍照的云台。在这里,你可以看到我们的成品是如何工作的。

    主要材料
    1、树莓派3 X1
    2、摄像头模块 X1
    3、9G 180°微型舵机 X2
    4、迷你平移/倾斜照相机平台 防振照相机支架(2个舵机)
    5、电阻1K欧姆 X2(可选)
    6、金属部件
    7、固定带等(用于构建云台平台)
    你可以购买一个成品的云台平台舵机或自己制作。

    PWM如何工作
    树莓派不能直接输出模拟电信号,但我们可以使用PWM(脉宽调制)方法来模拟这一点。我们制作一个固定频率的数字信号,在那里我们将改变脉冲宽度,将“转换”改为“平均”输出电压的电平,如下图所示:
    2.gif
    我们可以使用这个“平均”电压水平来控制LED亮度,例如:
    3.gif
    请注意频率本身不是重点,而是“占空比”,即脉冲“高”的时间除以波周期之间的关系。例如,假设我们在树莓派的 GPIO上产生一个50Hz的脉冲频率。周期(p)将是频率的倒数或20ms(1 / f)。如果我们的LED达到“半”亮度,我们的占空比必须为50%,这意味着“脉冲”将是10ms的“高”。

    这个原理对于我们来说非常重要,一旦使用“占空比”来定义舵机位置,如下所示,它用于控制舵机的位置。

    安装部件
    4.jpg
    5.jpg

    舵机将连接到外部5V电源,其数据引脚(我的项目中,黄色接线)连接到树莓派GPIO如下:
    • GPIO 17 ==>仰角舵机
    • GPIO 27 ==>平移舵机
    不要忘记将GND连接在一起 ==> 树莓派 – 舵机 – 外部电源。

    你可以在树莓派的GPIO和服务器数据输入引脚之间串联一个1K欧姆的电阻。 如果发生舵机故障,这将保护你的树莓派。


    舵机的校准
    6.jpg
    7.jpg
    8.jpg

    1、首先你要弄清楚你购买到的舵机的主要特点。在这个项目中,我使用的是Power Pro SG90。
    以下是它的数据表,我们可以参考一下:
    • 范围:180°
    • 电源:4.8V(外部可使用USB 5VDC电源)
    • 工作频率:50Hz(周期:20 ms)
    • 脉冲宽度:从1ms到2ms

    2、理论上,舵机运转的位置
    • 初始位置(0°):1ms脉冲到数据终端。
    • 中间位置(90°):1.5ms脉冲到数据终端。
    • 最终位置(180°):2 ms脉冲到数据终端。

    3、使用Python编写舵机位置,了解上述位置相应的“占空比”非常重要,我们来做一些计算:
    • 初始位置==>(0°)脉冲宽度==> 1ms ==>占空比= 1ms / 20ms ==> 2.0%
    • 中间位置(90°)==> 1.5 ms的脉冲宽度==>占空比= 1.5ms / 20ms ==> 7.5%
    • 最终位置(180°)==> 2 ms的脉冲宽度==>占空比= 2ms / 20ms ==> 10%

    所以占空比应该在2%到10%的范围内变化。

    4、单独测试舵机
    打开树莓派终端并以“sudo”启动你的 Python 3 shell 编辑器(你可能是“超级用户”来处理GPIO):
    1. sudo python3
    复制代码
    在Python Shell上导入RPI.GPIO模块并作为GPIO:
    1. import RPi.GPIO as GPIO
    复制代码
    定义你自己想要使用引脚编号方案(BCM或BOARD)。我用BOARD做了这个测试,所以我使用的引脚为物理引脚(GPIO 17 =引脚11和GPIO 27引脚13)。对我来说,很容易识别它们,并且在测试过程中不会犯错误(在最终的程序中,我将使用BCM)。按照自己的喜好来选择:
    1. GPIO.setmode(GPIO.BOARD)
    复制代码
    定义你要使用的舵机引脚:
    1. tiltPin = 11
    复制代码
    如果你已经使用了BCM方案,相反的,将最后2个命令应该替换为:
    1. GPIO.setmode(GPIO.BCM)
    2. tiltPin = 17
    复制代码
    现在,我们必须指定这个引脚将为“输出”
    1. GPIO.setup(tiltPin, GPIO.OUT)
    复制代码
    而且,这个引脚上产生的频率,对于我们的舵机来说应该是50Hz:
    1. tilt = GPIO.PWM(tiltPin, 50)
    复制代码
    现在,让我们开始在引脚上设置一个初始占空比(我们将它保持为“0”)的PWM信号:
    1. tilt = start(0)
    复制代码
    现在,你可以输入不同的占空比值,观察舵机的运动。让我们从2%开始,看看会发生什么(我们观察舵机从“零位”开始):
    1. tilt.ChangeDutyCycle(2)
    复制代码

    我项目的情况是,当我将占空比改为3%时,舵机进入零位。我观察到舵机停留在同一位置,开始以大于3%的占空比移动。所以,3%是我的初始位置(o°)。同样的情况发生在10%,我的舵机超过这个数值,最终达到13%。所以对于这个舵机,最终结果是:
    0°==>占空比3%
    90°==>占空比8%
    180°==>占空比13%

    完成测试后,你必须停止PWM并清理GPIO:
    1. tilt= stop()
    2. GPIO.cleanup()
    复制代码

    上面终端将打印出屏幕显示的数据,我两个舵机的结果非常的相似。你的范围可以不同。

    创建 Python 脚本
    9.jpg

    正如我们在上一步所看到的那样,发送到我们舵机的PWM命令要与“占空比”相对应。但通常情况下,我们必须以角度作为参数来控制舵机。因此,我们必须将“角度”转换为我们工作周期中比较常见的常量,要被Pi所理解的。

    怎么做?很简单!我们知道占空比范围从3%到13%,这相当于从0到180度范围内的角度。另外,我们知道这些变化是线性的,所以我们可以构建一个如上所示的比例模式。所以,给定一个角度,我们可以有一个相应的工作周期:
    dutycycle = angle/18 + 3
    保存这个公式。 我们将在下一个代码中使用它。

    我们来创建一个Python脚本来进行测试。 基本上,我们将重复我们之前在Python Shell上做的事情:

    1. from time import sleep
    2. import RPi.GPIO as GPIO
    3. GPIO.setmode(GPIO.BCM)
    4. GPIO.setwarnings(False)

    5. def setServoAngle(servo, angle):
    6.     pwm = GPIO.PWM(servo, 50)
    7.     pwm.start(8)
    8.     dutyCycle = angle / 18. + 3.
    9.     pwm.ChangeDutyCycle(dutyCycle)
    10.     sleep(0.3)
    11.     pwm.stop()

    12. if __name__ == '__main__':
    13.     import sys
    14.     servo = int(sys.argv[1])
    15.     GPIO.setup(servo, GPIO.OUT)
    16.     setServoAngle(servo, int(sys.argv[2]))
    17.     GPIO.cleanup()
    复制代码

    上述代码的核心是设置舵机和角度的函数。 该函数接收参数、舵机、 GPIO编号和舵机必须定位的角度值。 一旦这个函数的输入是“角度”,我们必须使用之前开发的公式将其转换为百分比的占空比。

    脚本执行时,必须输入参数,舵机GPIO和角度。

    例如:
    1. sudo python3 angleServoCtrl.py 17 45
    复制代码
    上述命令会将舵机连接到GPIO 17并且以“仰角”45度定位。 一个类似的命令可以用于平移伺服控制(在“方位角”中位置为45度):
    1. sudo python angleServoCtrl.py 27 45
    复制代码
    文件 angleServoCtrl.py 可以在我的 GitHub 下载。

    平台移动机制
    10.jpg

    “平板”舵机将“水平”移动摄像机(“方位角”),而我们的“仰角”舵机将“垂直移动”(仰角)。
    下图显示了云台机制的工作原理:
    11.jpg

    在项目进行过程中,我们不会走向“极端”,我们只能使用30到150度的云台机制。 这个范围足够用于相机。

    平台机械结构

    12.jpg
    13.jpg
    14.jpg
    15.jpg

    现在将两个舵机作为云台进行组装。 你可以在这里做两件事。 购买一个平台或根据您的需求构建自己的平台机制。
    我做了一个样板出来,只是将两个舵机捆绑在一起,并用上图中所示的旧玩具的小金属件搭建起来。

    组装电动云台组件
    16.jpg
    17.jpg
    18.jpg

    组装好云台机制后,请按照图片进行全面电气连接。
    1、关闭你的Pi。
    2、进行所有电气连接。
    3、仔细检查它。
    4、首先打开你的Pi。
    5、如果一切正常,请给舵机供电。
    本教程中我们不会将如何设置相机进行展开。

    Python 脚本
    让我们创建一个Python脚本来同时控制两个舵机:
    1. from time import sleep
    2. import RPi.GPIO as GPIO
    3. GPIO.setmode(GPIO.BCM)
    4. GPIO.setwarnings(False)

    5. pan = 27
    6. tilt = 17

    7. GPIO.setup(tilt, GPIO.OUT) # white => TILT
    8. GPIO.setup(pan, GPIO.OUT) # gray ==> PAN

    9. def setServoAngle(servo, angle):
    10.     assert angle >=30 and angle <= 150
    11.     pwm = GPIO.PWM(servo, 50)
    12.     pwm.start(8)
    13.     dutyCycle = angle / 18. + 3.
    14.     pwm.ChangeDutyCycle(dutyCycle)
    15.     sleep(0.3)
    16.     pwm.stop()

    17. if __name__ == '__main__':
    18.     import sys
    19.     if len(sys.argv) == 1:
    20.         setServoAngle(pan, 90)
    21.         setServoAngle(tilt, 90)
    22.     else:
    23.         setServoAngle(pan, int(sys.argv[1])) # 30 ==> 90 (middle point) ==> 150
    24.         setServoAngle(tilt, int(sys.argv[2])) # 30 ==> 90 (middle point) ==> 150
    25.     GPIO.cleanup()
    复制代码

    脚本执行时,必须输入参数,平移角度和倾斜角度。 例如:
    1. sudo python3 servoCtrl.py 45 120
    复制代码
    上述命令将使“水平/倾斜”平台在“方位角”(水平角)和120度“仰角”(倾斜角)方向上定位为45°。 请注意,如果未输入任何参数,则默认平移和倾斜角度均为90°。
    文件
    servoCtrl.py可以在我的GitHub下载。

    服务器的环路测试
    现在让我们创建一个Python脚本来自动测试所有的舵机:
    1. from time import sleep
    2. import RPi.GPIO as GPIO
    3. GPIO.setmode(GPIO.BCM)
    4. GPIO.setwarnings(False)

    5. pan = 27
    6. tilt = 17

    7. GPIO.setup(tilt, GPIO.OUT) # white => TILT
    8. GPIO.setup(pan, GPIO.OUT) # gray ==> PAN

    9. def setServoAngle(servo, angle):
    10.     assert angle >=30 and angle <= 150
    11.     pwm = GPIO.PWM(servo, 50)
    12.     pwm.start(8)
    13.     dutyCycle = angle / 18. + 3.
    14.     pwm.ChangeDutyCycle(dutyCycle)
    15.     sleep(0.3)
    16.     pwm.stop()

    17. if __name__ == '__main__':  
    18.     for i in range (30, 160, 15):
    19.         setServoAngle(pan, i)
    20.         setServoAngle(tilt, i)
    21.      
    22.     for i in range (150, 30, -15):
    23.         setServoAngle(pan, i)
    24.         setServoAngle(tilt, i)
    25.          
    26.     setServoAngle(pan, 100)
    27.     setServoAngle(tilt, 90)   
    28.     GPIO.cleanup()
    复制代码
    程序将自动从30°到150°两个角度进行循环。

    结果如下:
    我只连接了一台示波器来说明如前所述的PWM理论。
    19.png
    以上源代码 servoTest.py 可以在GitHub下载。

    结语
    一如既往,我希望这个项目能够帮助他人进入激动人心的电子世界!
    有关详细信息和最终代码,请访问我的 GitHub 仓库:
    RPi-Pan-Tilt-Servo-Control





    回复

    使用道具 举报

  • TA的每日心情
    难过
    2021-2-27 22:16
  • 签到天数: 1568 天

    连续签到: 1 天

    [LV.Master]伴坛终老

    发表于 2019-4-24 12:00:54 | 显示全部楼层
    看来楼主真是人才 522.jpg
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-4-19 16:21 , Processed in 0.120365 second(s), 18 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.