TA的每日心情 | 开心 2018-9-6 15:08 |
---|
签到天数: 11 天 连续签到: 1 天 [LV.3]偶尔看看II
|
本帖最后由 ky123 于 2018-1-31 14:07 编辑
感谢E络盟提供的助赛基金。
本章节的编写是为了下一步视频安防做准备,也遥控小车的扩展!
因为选择的USB摄像头为定焦摄像头,只有通过调整自身的状态才形成清晰的成像!当通过运动电机将目标调整至显示窗口时,由于距离发生了变化成像往往是模糊的!因此,在保证距离稳定成像清晰的前提下,调整舵机的俯仰位置将目标调整至显示窗内!
本章的两个工作:
1)底层驱动,PWM控制舵机;
2)操作应用,web实时控制舵机比摄像头显示目标
DuerOS和小车运动电机占用的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下载和测试)- rm pigpio.zip
- sudo rm -rf PIGPIO
- wget abyz.co.uk/rpi/pigpio/pigpio.zip
- unzip pigpio.zip
- cd PIGPIO
- make
- sudo make install
复制代码 最好也测试下是否安装成功,GPIO 25 (pin 22).连接一个LED,LED灯会根据测试类项响应!- ./x_pigpio.py # check Python I/F to daemon
复制代码 2.编写程序
官方提供了很多example,deamo中有提供操作实例- #!/usr/bin/env python
- # servo_demo.py
- # 2016-10-07
- # Public Domain
- # servo_demo.py # Send servo pulses to GPIO 4.
- # servo_demo.py 23 24 25 # Send servo pulses to GPIO 23, 24, 25.
- import sys
- import time
- import random
- import pigpio
- NUM_GPIO=32
- MIN_WIDTH=1000
- MAX_WIDTH=2000
- step = [0]*NUM_GPIO
- width = [0]*NUM_GPIO
- used = [False]*NUM_GPIO
- pi = pigpio.pi()
- if not pi.connected:
- exit()
- if len(sys.argv) == 1:
- G = [4]
- else:
- G = []
- for a in sys.argv[1:]:
- G.append(int(a))
-
- for g in G:
- used[g] = True
- step[g] = random.randrange(5, 25)
- if step[g] % 2 == 0:
- step[g] = -step[g]
- width[g] = random.randrange(MIN_WIDTH, MAX_WIDTH+1)
- print("Sending servos pulses to GPIO {}, control C to stop.".
- format(' '.join(str(g) for g in G)))
- while True:
- try:
- for g in G:
- pi.set_servo_pulsewidth(g, width[g])
- # print(g, width[g])
- width[g] += step[g]
- if width[g]<MIN_WIDTH or width[g]>MAX_WIDTH:
- step[g] = -step[g]
- width[g] += step[g]
- time.sleep(0.1)
- except KeyboardInterrupt:
- break
- print("\nTidying up")
- for g in G:
- pi.set_servo_pulsewidth(g, 0)
- pi.stop()
复制代码 该库函数中关于舵机控制有编写专门的API,set_servo_pulsewidth(user_gpio, pulsewidth)其中gpio遵循BCM编码规则!- set_servo_pulsewidth Start/Stop servo pulses on a GPIO
- get_servo_pulsewidth Get servo pulsewidth set on a GPIO
复制代码 重头戏来了!参考以上程序修改我们的运动控制程序即server/pi_car/views.py,在其中添加舵机控制程序段!本次也修改的之前对运动电机GPIO口的配置方式,在开始采用全局变量定义GPIO,这样大家根据个人自身情况更换GPIO更方便!
注意:本项目中电机和舵机由于使用的库不一样,编码方式也不一样!GPIO配置时数值一定要注意!- from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash
- from contextlib import closing
- from pi_car import app
- import re
- import RPi.GPIO as GPIO
- import pigpio
- import time
- import sys
- pi = pigpio.pi()
- if not pi.connected:
- exit()
- # for BCD.GPIO
- SERVO_GPIO = 4
- # for RPi.GPIO
- MOTOR_LEFT1_GPIO = 19
- MOTOR_LEFT2_GPIO = 21
- MOTOR_RIGHT1_GPIO = 22
- MOTOR_RIGHT2_GPIO = 24
-
- pi.set_mode(SERVO_GPIO, pigpio.OUTPUT)
- MIN_WIDTH = 500
- MAX_WIDTH = 1200
- width = 750
- step = 50
- @app.route('/')
- def show_index():
- return render_template('home.html')
- @app.route("/login", methods=["GET", "POST"])
- def login():
- if request.method=="GET":
- return "get"+request.form["user"]
- elif request.method=="POST":
- return "post"
- @app.route('/ctl',methods=['GET','POST'])
- def ctrl_id():
- if request.method == 'POST':
- id=request.form['id']
- GPIO.setmode(GPIO.BOARD)
- GPIO.setwarnings(False)
- GPIO.setup(MOTOR_LEFT1_GPIO,GPIO.OUT)
- GPIO.setup(MOTOR_LEFT2_GPIO,GPIO.OUT)
- GPIO.setup(MOTOR_RIGHT1_GPIO,GPIO.OUT)
- GPIO.setup(MOTOR_RIGHT2_GPIO,GPIO.OUT)
- if id == 't_left':
- t_left()
- return "left"
- elif id == 't_right':
- t_right()
- return "right"
- elif id == 't_up':
- t_up()
- return "up"
- elif id == 't_down':
- t_down()
- return "down"
- elif id == 't_stop':
- t_stop()
- return "stop"
- elif id == 's_down':
- s_down()
- return "servo_down"
- elif id == 's_up':
- s_up()
- return "servo_up"
- return redirect(url_for('show_index'))
- def t_stop():
- GPIO.output(MOTOR_LEFT1_GPIO, False)
- GPIO.output(MOTOR_LEFT2_GPIO, False)
- GPIO.output(MOTOR_RIGHT1_GPIO, False)
- GPIO.output(MOTOR_RIGHT2_GPIO, False)
- def t_up():
- GPIO.output(MOTOR_LEFT1_GPIO, True)
- GPIO.output(MOTOR_LEFT2_GPIO, False)
- GPIO.output(MOTOR_RIGHT1_GPIO, True)
- GPIO.output(MOTOR_RIGHT2_GPIO, False)
- def t_down():
- GPIO.output(MOTOR_LEFT1_GPIO, False)
- GPIO.output(MOTOR_LEFT2_GPIO, True)
- GPIO.output(MOTOR_RIGHT1_GPIO, False)
- GPIO.output(MOTOR_RIGHT2_GPIO, True)
- def t_left():
- GPIO.output(MOTOR_LEFT1_GPIO, False)
- GPIO.output(MOTOR_LEFT2_GPIO, True)
- GPIO.output(MOTOR_RIGHT1_GPIO, True)
- GPIO.output(MOTOR_RIGHT2_GPIO, False)
- def t_right():
- GPIO.output(MOTOR_LEFT1_GPIO, True)
- GPIO.output(MOTOR_LEFT2_GPIO, False)
- GPIO.output(MOTOR_RIGHT1_GPIO, False)
- GPIO.output(MOTOR_RIGHT2_GPIO, True)
- def s_down():
- global width
- print(width)
- if width>MIN_WIDTH:
- width -=step
- pi.set_servo_pulsewidth(SERVO_GPIO,width)
- time.sleep(0.1)
- else:
- width = MIN_WIDTH
- print(width)
- def s_up():
- global width
- print(width)
- if width<MAX_WIDTH:
- width +=step
- pi.set_servo_pulsewidth(SERVO_GPIO,width)
- time.sleep(0.1)
- else:
- width = MAX_WIDTH
- print(width)
复制代码 代码中通过MIN_WIDTH和MAX_WIDTH限定舵机的控制范围!根据实际情况修改,避免结构干涉引起舵机堵转!
web中添加舵机控制的图标和相关程序,在server/pi_car/static/img路径下添加舵机控制的图片
servo_img.zip
(9.93 KB, 下载次数: 1)
|
|