查看: 5479|回复: 0

[大赛作品提交] 【进阶六】家庭陪伴小机器人遥控舵机姿态

[复制链接]
  • TA的每日心情
    开心
    2018-9-6 15:08
  • 签到天数: 11 天

    连续签到: 1 天

    [LV.3]偶尔看看II

    发表于 2018-1-8 15:23:03 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 ky123 于 2018-1-31 14:07 编辑

    感谢E络盟提供的助赛基金。
    本章节的编写是为了下一步视频安防做准备,也遥控小车的扩展!

    因为选择的USB摄像头为定焦摄像头,只有通过调整自身的状态才形成清晰的成像!当通过运动电机将目标调整至显示窗口时,由于距离发生了变化成像往往是模糊的!因此,在保证距离稳定成像清晰的前提下,调整舵机的俯仰位置将目标调整至显示窗内!

    本章的两个工作:
    1)底层驱动,PWM控制舵机;
    2)操作应用,web实时控制舵机比摄像头显示目标

    DuerOS和小车运动电机占用的GPIO如下:
    实际使用GPIO.jpg

    树莓派3B详解GPIO功能

    树莓派3B详解GPIO功能

    树莓派3B_GPIO编码规则

    树莓派3B_GPIO编码规则

    树莓派只有一路 硬件PWM 输出( GPIO.1即BOARD中的引脚12,BCM编码中18,wiringPi编码中1 );
    同时 wiringPi 库为我们提供了用软件 多线程 实现的PWM输出,我们可以利用这个库提供的函数很方便的将 任意GPIO 配置为PWM输出,即soft PWM;个人模拟的PWM可能存在精度不准的情况)

    由第一张图可以看出,硬件PWM已被DuerOS占用了! python提供的RPI.GPIO提供的PWM输出为硬件PWM,且未提供软件的PWM,也以使用wiringPi编码,软件模拟PWM;
    另外也有人使用pigpio library来控制GPIO口,pigpio是一个允许控制GPIO的C语言库,同时pigpio是一个适用于树莓派的Python 模块,允许用过pigpio daemon程序控制通用GPIO口,不仅有PWM库,同时还有现成的Servo控制API(其实该库还是很强大的,此外还有IIC/SPI/ADC/DMA等,推荐给大家),因此本设计采用pigpio库来实现舵机控制!注意:所有的GPIO是按BCD编码命名。

    1.安装pigpio库(pigpio下载和测试)
    1. rm pigpio.zip
    2. sudo rm -rf PIGPIO
    3. wget abyz.co.uk/rpi/pigpio/pigpio.zip
    4. unzip pigpio.zip
    5. cd PIGPIO
    6. make
    7. sudo make install
    复制代码
    最好也测试下是否安装成功,GPIO 25 (pin 22).连接一个LED,LED灯会根据测试类项响应!
    1. ./x_pigpio.py   # check Python I/F to daemon
    复制代码
    2.编写程序
    官方提供了很多example,deamo中有提供操作实例
    1. #!/usr/bin/env python

    2. # servo_demo.py
    3. # 2016-10-07
    4. # Public Domain

    5. # servo_demo.py          # Send servo pulses to GPIO 4.
    6. # servo_demo.py 23 24 25 # Send servo pulses to GPIO 23, 24, 25.

    7. import sys
    8. import time
    9. import random
    10. import pigpio

    11. NUM_GPIO=32

    12. MIN_WIDTH=1000
    13. MAX_WIDTH=2000

    14. step = [0]*NUM_GPIO
    15. width = [0]*NUM_GPIO
    16. used = [False]*NUM_GPIO

    17. pi = pigpio.pi()

    18. if not pi.connected:
    19.    exit()

    20. if len(sys.argv) == 1:
    21.    G = [4]
    22. else:
    23.    G = []
    24.    for a in sys.argv[1:]:
    25.       G.append(int(a))
    26.    
    27. for g in G:
    28.    used[g] = True
    29.    step[g] = random.randrange(5, 25)
    30.    if step[g] % 2 == 0:
    31.       step[g] = -step[g]
    32.    width[g] = random.randrange(MIN_WIDTH, MAX_WIDTH+1)

    33. print("Sending servos pulses to GPIO {}, control C to stop.".
    34.    format(' '.join(str(g) for g in G)))

    35. while True:

    36.    try:

    37.       for g in G:

    38.          pi.set_servo_pulsewidth(g, width[g])

    39.          # print(g, width[g])

    40.          width[g] += step[g]

    41.          if width[g]<MIN_WIDTH or width[g]>MAX_WIDTH:
    42.             step[g] = -step[g]
    43.             width[g] += step[g]

    44.       time.sleep(0.1)

    45.    except KeyboardInterrupt:
    46.       break

    47. print("\nTidying up")

    48. for g in G:
    49.    pi.set_servo_pulsewidth(g, 0)

    50. pi.stop()
    复制代码
    该库函数中关于舵机控制有编写专门的API,set_servo_pulsewidth(user_gpio, pulsewidth)其中gpio遵循BCM编码规则!
    1. set_servo_pulsewidth        Start/Stop servo pulses on a GPIO
    2. get_servo_pulsewidth        Get servo pulsewidth set on a GPIO
    复制代码
    重头戏来了!参考以上程序修改我们的运动控制程序即server/pi_car/views.py,在其中添加舵机控制程序段!本次也修改的之前对运动电机GPIO口的配置方式,在开始采用全局变量定义GPIO,这样大家根据个人自身情况更换GPIO更方便!
    注意:本项目中电机和舵机由于使用的库不一样,编码方式也不一样!GPIO配置时数值一定要注意!
    1. from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash
    2. from contextlib import closing
    3. from pi_car import app
    4. import re
    5. import RPi.GPIO as GPIO
    6. import pigpio
    7. import time
    8. import sys

    9. pi = pigpio.pi()
    10. if not pi.connected:
    11.    exit()
    12. # for BCD.GPIO      
    13. SERVO_GPIO = 4
    14. # for RPi.GPIO      
    15. MOTOR_LEFT1_GPIO = 19
    16. MOTOR_LEFT2_GPIO = 21
    17. MOTOR_RIGHT1_GPIO = 22
    18. MOTOR_RIGHT2_GPIO = 24      
    19.       
    20. pi.set_mode(SERVO_GPIO, pigpio.OUTPUT)
    21. MIN_WIDTH = 500
    22. MAX_WIDTH = 1200
    23. width = 750
    24. step = 50

    25. @app.route('/')
    26. def show_index():
    27.         return render_template('home.html')

    28. @app.route("/login", methods=["GET", "POST"])
    29. def login():
    30.         if request.method=="GET":
    31.                 return "get"+request.form["user"]
    32.         elif request.method=="POST":
    33.                 return "post"

    34. @app.route('/ctl',methods=['GET','POST'])
    35. def ctrl_id():
    36.         if request.method == 'POST':
    37.                 id=request.form['id']
    38.                 GPIO.setmode(GPIO.BOARD)
    39.                 GPIO.setwarnings(False)
    40.                 GPIO.setup(MOTOR_LEFT1_GPIO,GPIO.OUT)
    41.                 GPIO.setup(MOTOR_LEFT2_GPIO,GPIO.OUT)
    42.                 GPIO.setup(MOTOR_RIGHT1_GPIO,GPIO.OUT)
    43.                 GPIO.setup(MOTOR_RIGHT2_GPIO,GPIO.OUT)

    44.                 if id == 't_left':
    45.                         t_left()
    46.                         return "left"
    47.                 elif id == 't_right':
    48.                         t_right()
    49.                         return "right"
    50.                 elif id == 't_up':
    51.                         t_up()
    52.                         return "up"
    53.                 elif id == 't_down':
    54.                         t_down()
    55.                         return "down"
    56.                 elif id == 't_stop':
    57.                         t_stop()
    58.                         return "stop"

    59.                 elif id == 's_down':
    60.                         s_down()
    61.                         return "servo_down"

    62.                 elif id == 's_up':
    63.                         s_up()
    64.                         return "servo_up"


    65.         return redirect(url_for('show_index'))

    66. def t_stop():
    67.         GPIO.output(MOTOR_LEFT1_GPIO, False)
    68.         GPIO.output(MOTOR_LEFT2_GPIO, False)
    69.         GPIO.output(MOTOR_RIGHT1_GPIO, False)
    70.         GPIO.output(MOTOR_RIGHT2_GPIO, False)

    71. def t_up():
    72.         GPIO.output(MOTOR_LEFT1_GPIO, True)
    73.         GPIO.output(MOTOR_LEFT2_GPIO, False)
    74.         GPIO.output(MOTOR_RIGHT1_GPIO, True)
    75.         GPIO.output(MOTOR_RIGHT2_GPIO, False)

    76. def t_down():
    77.         GPIO.output(MOTOR_LEFT1_GPIO, False)
    78.         GPIO.output(MOTOR_LEFT2_GPIO, True)
    79.         GPIO.output(MOTOR_RIGHT1_GPIO, False)
    80.         GPIO.output(MOTOR_RIGHT2_GPIO, True)

    81. def t_left():
    82.         GPIO.output(MOTOR_LEFT1_GPIO, False)
    83.         GPIO.output(MOTOR_LEFT2_GPIO, True)
    84.         GPIO.output(MOTOR_RIGHT1_GPIO, True)
    85.         GPIO.output(MOTOR_RIGHT2_GPIO, False)

    86. def t_right():
    87.         GPIO.output(MOTOR_LEFT1_GPIO, True)
    88.         GPIO.output(MOTOR_LEFT2_GPIO, False)
    89.         GPIO.output(MOTOR_RIGHT1_GPIO, False)
    90.         GPIO.output(MOTOR_RIGHT2_GPIO, True)

    91. def s_down():
    92.         global width
    93.         print(width)
    94.         if width>MIN_WIDTH:
    95.                 width -=step
    96.                 pi.set_servo_pulsewidth(SERVO_GPIO,width)
    97.                 time.sleep(0.1)
    98.         else:
    99.                 width = MIN_WIDTH
    100.         print(width)

    101. def s_up():
    102.         global width
    103.         print(width)
    104.         if width<MAX_WIDTH:
    105.                 width +=step
    106.                 pi.set_servo_pulsewidth(SERVO_GPIO,width)
    107.                 time.sleep(0.1)
    108.         else:
    109.                 width = MAX_WIDTH
    110.         print(width)
    复制代码
    代码中通过MIN_WIDTH和MAX_WIDTH限定舵机的控制范围!根据实际情况修改,避免结构干涉引起舵机堵转!
    web中添加舵机控制的图标和相关程序,在server/pi_car/static/img路径下添加舵机控制的图片
    servo_img.zip (9.93 KB, 下载次数: 1)
    回复

    使用道具 举报

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

    本版积分规则

    关闭

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



    手机版|小黑屋|与非网

    GMT+8, 2024-5-3 07:41 , Processed in 0.128786 second(s), 18 queries , MemCache On.

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

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.