赞
踩
前期内容提要:
在完成网络摄像头的前期准备并实现监控画面的正常传输后,我们需要实现工程的第二个需求,监控画面角度的实时遥控。
基本思路:凭借两个舵机实现摄像头水平方向与垂直方向转动;选用Python的RPi.GPIO模块控制舵机所连针脚实现舵机的旋转以控制摄像头拍摄画面角度;后续工程由于需要引入异步io框架搭建Web控制页面,因此舵机的方向控制程式和摄像头主控制程式应当分离以保障代码的简洁性和可读性:
文件 | 功能 |
---|---|
/steering.py | 舵机控制程序 |
/config.ini | 配置文件(写入舵机接入的针脚数、舵机初始角度、最大最小旋转角度等信息) |
/index.py | 主程序(后续python异步io框架tornado也会在此文件中加工) |
SG90 脉冲周期为20毫秒(millisecond),脉宽0.5ms-2.5ms对应的角度-90到+90度,范围180度(3度左右偏差)。
# -*- coding: UTF-8 -*-
import RPi.GPIO as GPIO
import time
import atexit
class Steering:
max_delay = 0.2
min_delay = 0.04
def __init__(self, channel, init_position, min_angle, max_angle, speed):
self.channel = channel
self.init_position = init_position
self.position = init_position
self.min_angle = min_angle
self.max_angle = max_angle
self.speed = speed
atexit.register(GPIO.cleanup)
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(self.channel, GPIO.OUT, initial=False)
self.pwm = GPIO.PWM(self.channel, 50) # PWM
self.pwm.start(2.5 + 10 * self.position / 180) # 让舵机转到初始位置
time.sleep(Steering.max_delay)
self.pwm.ChangeDutyCycle(0)
time.sleep(Steering.min_delay)
正转
、要么反转
,再加上一个位置初始化
,因此只需要在Steering类中定义三个方法。 def forwardRotation(self):
print("current position 1: " + str(self.position))
if (self.position + self.speed) <= self.max_angle:
self.position = self.position + self.speed
self.pwm.ChangeDutyCycle(2.5 + 10 * self.position / 180) # 设置舵机角度
time.sleep(Steering.min_delay)
self.pwm.ChangeDutyCycle(0) # 舵机回到中位
time.sleep(Steering.min_delay)
print("current position 2: " + str(self.position))
def reverseRotation(self):
print("current position 1: " + str(self.position))
if (self.position - self.speed) >= self.min_angle:
self.position = self.position - self.speed
self.pwm.ChangeDutyCycle(2.5 + 10 * self.position / 180) # 设置舵机角度
time.sleep(Steering.min_delay)
self.pwm.ChangeDutyCycle(0) # 舵机回到中位
time.sleep(Steering.min_delay)
print("current position 2: " + str(self.position))
def reset(self):
print("current position 1: " + str(self.position))
self.position = self.init_position
self.pwm.start(2.5 + 10 * self.init_position / 180) # 让舵机转到初始位置
time.sleep(Steering.max_delay)
self.pwm.ChangeDutyCycle(0)
time.sleep(Steering.min_delay)
print("current position 2: " + str(self.position))
我的垂直移动舵机GPIO口BOARD编码为7;左右移动舵机GPIO口BOARD编码为12
[camera]
# 控制摄像灯垂直移动的舵机
HIntfNum = 7
HInitPosition = 100 #略微抬升10度以符合通常拍摄角度
HMinPosition = 30 #设置边界以防止摄像头俯角过大与舵机碰撞摩擦减损寿命
HMaxPosition = 180
HSpeed = 5
# 控制摄像灯水平(左右)移动的舵机
VIntfNum = 12
VInitPosition = 120 #固定云台偏移角度还原后的初始角度
VMinPosition = 0
VMaxPosition = 180
VSpeed = 5
# -*- coding: UTF-8 -*-
import sys
import RPi.GPIO as GPIO
import time
import sys
from steering import Steering
import tornado.ioloop
import tornado.web
import tornado.httpserver
import tornado.options
from tornado.options import define,options
import configparser
import RPi.GPIO as GPIO
class Camera:
def __init__(self):
config = configparser.ConfigParser()
config.read("./config.ini")
HIntfNum = config.getint("camera", "HIntfNum")
HInitPosition = config.getint("camera", "HInitPosition")
HMinPosition = config.getint("camera", "HMinPosition")
HMaxPosition = config.getint("camera", "HMaxPosition")
HSpeed = config.getint("camera", "HSpeed")
VIntfNum = config.getint("camera", "VIntfNum")
VInitPosition = config.getint("camera", "VInitPosition")
VMinPosition = config.getint("camera", "VMinPosition")
VMaxPosition = config.getint("camera", "VMaxPosition")
VSpeed = config.getint("camera", "VSpeed")
self.HCameraControl = Steering(HIntfNum, HInitPosition,
HMinPosition, HMaxPosition, HSpeed)
self.VCameraControl = Steering(VIntfNum, VInitPosition,
VMinPosition, VMaxPosition, VSpeed)
向左 向右 向上 向下 复位
五种情况下舵机移动的方法。(注意摄像头左右移动的镜面原理) def cameraRotate(self,direction):
if direction == "A":
self.HCameraControl.forwardRotation()
elif direction == "D":
self.HCameraControl.reverseRotation()
elif direction == "W":
self.VCameraControl.forwardRotation()
elif direction == "S":
self.VCameraControl.reverseRotation()
elif direction == "Q":
self.HCameraControl.reset()
self.VCameraControl.reset()
else:
print("D, A, W, S or Q(reset)")
camera = Camera()
def run(dir):
camera.cameraRotate(dir)
注意:camera = Camera()一定要写在run方法的外头,不然舵机控制程式(/steering.py)会不停调用 self.position = init_position,致使舵机无法正常记录 self.position(current position 2)。
当然了,做了这么多,如果无法直观的看到舵机的旋转,相信大家会放心不下,这里要感谢 weixin_42534940 博主给出的方法:采用input()给direction赋值的方式检测程式,注释上面的camera = Camera()
后,创建一个程式执行入口:
if __name__ == "__main__":
camera = Camera()
while(True):
direction = input("Please input direction: ")
camera.cameraRotate(direction)
在回显当前位置的同时,我们能看到摄像头拍摄角度随着舵机的转向而转向。检测完成后记得及时删除测试代码以便工程的后续开展。
至此,我们基于python3成功控制两自由度舵机,实现了摄像头拍摄角度的遥控(源码已上传),下一章将和大家共同解决的主要问题是如何通过操控Web网页的方式给direction赋值,实现网页对摄像头拍摄角度的操控,完成网络摄像头控制功能雏形。
后期内容提要:
如果您有任何疑问或者好的建议,期待你的留言与评论!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。