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


前期内容提要:


在完成网络摄像头的前期准备并实现监控画面的正常传输后,我们需要实现工程的第二个需求,监控画面角度的实时遥控在这里插入图片描述
基本思路:凭借两个舵机实现摄像头水平方向与垂直方向转动;选用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赋值,实现网页对摄像头拍摄角度的操控,完成网络摄像头控制功能雏形。


后期内容提要:


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

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邓大帅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值