【树莓派-网络监控(3)角度遥控】基于python3控制两自由度舵机,实现摄像头拍摄角度的遥控

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/deng_xj/article/details/98620290

前期内容提要:


在完成网络摄像头的前期准备并实现监控画面的正常传输后,我们需要实现工程的第二个需求,监控画面角度的实时遥控在这里插入图片描述
基本思路:凭借两个舵机实现摄像头水平方向与垂直方向转动;选用Python的RPi.GPIO模块控制舵机所连针脚实现舵机的旋转以控制摄像头拍摄画面角度;后续工程由于需要引入异步io框架搭建Web控制页面,因此舵机的方向控制程式和摄像头主控制程式应当分离以保障代码的简洁性和可读性:

文件 功能
/steering.py 舵机控制程序
/config.ini 配置文件(写入舵机接入的针脚数、舵机初始角度、最大最小旋转角度等信息)
/index.py 主程序(后续python异步io框架tornado也会在此文件中加工)

一、舵机控制程式(/steering.py)编写思路

SG90 脉冲周期为20毫秒(millisecond),脉宽0.5ms-2.5ms对应的角度-90到+90度,范围180度(3度左右偏差)。

1. 用Python的GPIO提供的PWM控制舵机。
# -*- 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)
2. 舵机要么正转、要么反转,再加上一个位置初始化,因此只需要在Steering类中定义三个方法。
3. 程式仅用于主程序的调用,无需编写执行命令。
    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))        

二、填写配置文件(/config.ini)

我的垂直移动舵机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

在这里插入图片描述


三、摄像头主控制程式(/index.py)编写思路
1. 定义一个Camera类,调用配置文件(/config.ini)数值放入舵机控制程式(/steering.py)中去。
# -*- 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)
2. 在Camera类中写入向左 向右 向上 向下 复位五种情况下舵机移动的方法。(注意摄像头左右移动的镜面原理)
	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)")
3. 由于工程最后会通过键盘(屏幕)按压的方式为direction赋值,因此这里只需要为程式写上一个执行方法即可。
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赋值,实现网页对摄像头拍摄角度的操控,完成网络摄像头控制功能雏形。


后期内容提要:


如果您有任何疑问或者好的建议,期待你的留言与评论!

猜你喜欢

转载自blog.csdn.net/deng_xj/article/details/98620290