python有没有控制舵机的库 python控制舵机旋转_pwm控制舵机转动角度程序


今天我们在树莓派上面运行一个PyQt5的程序,可以通过GPIO口进行舵机转动,可以在Qt界面中操作。

我手里的舵机主要有SG90和MG995这两种,后者主要是组成的二度云台来使用,驱动方式基本都一样所以,所以今天就以SG90舵机的驱动为例。


python有没有控制舵机的库 python控制舵机旋转_python有没有控制舵机的库_02


python有没有控制舵机的库 python控制舵机旋转_Windows_03


一、软件编码

1、使用PyQt5设计界面

使用QtDesigner设计一个UI界面,保存为HomePage.ui文件,可以自行设计,主要目的是通过点击软件按钮,达到舵机旋转的目的,如下图:


python有没有控制舵机的库 python控制舵机旋转_python有没有控制舵机的库_04


2、将HomePage.ui文件转换为ui_HomePage.py,使用pyuic5命令或者在PyCharm中直接转换:

pyuic5 -o ui_HomePage.py HomePage.ui


python有没有控制舵机的库 python控制舵机旋转_舵机_05


这样我们就创建了一个UI界面,目录结构如下:


python有没有控制舵机的库 python控制舵机旋转_pwm控制舵机转动角度程序_06


显示效果如下:


python有没有控制舵机的库 python控制舵机旋转_pwm控制舵机转动角度程序_07


3、编写舵机驱动模块SteeringSG90Module.py

我在这里将驱动模块都放在了DeviceDriver目录下,大家可以根据自己的习惯设计目录结构,只要import的时候包含路径正确就行。


python有没有控制舵机的库 python控制舵机旋转_舵机_08


SteeringSG90Module.py文件的内容如下:


#!/usr/bin/env python
"""
SG90舵机控制驱动
"""
import platform
if (platform.system()=='Windows'):
 pass
else:
 import RPi.GPIO as GPIO
import time
from PyQt5.QtCore import *
global currDir
currDir = 'stop'
class SteeringSG90Worker(QObject):
 'SG90舵机工作线程'
 def __init__(self):
 super(SteeringSG90Worker,self).__init__()
 self.gpioFlag = False
 self.working = True
 self.angle = 0
 def __del__(self):
 '线程停止'
 self.working = False
   def setGPIO(self,servopin):
 self.ServoPin = servopin
 self.gpioFlag = True
   def initCheckSelf(self):
 '初始化自检'
 for i in range(0, 181, 10):
 self.p.ChangeDutyCycle(2.5 + 10 * i / 180)
         time.sleep(0.02)
 self.p.ChangeDutyCycle(0)
         time.sleep(0.2)
 for i in range(181, 0, -10):
 self.p.ChangeDutyCycle(2.5 + 10 * i / 180)
         time.sleep(0.02)
 self.p.ChangeDutyCycle(0)
         time.sleep(0.2)
 #自检完毕
 self.angle = 0
 self.gpioFlag = True
   def turnLeft(self):
 self.angle += 5
 if self.angle >= 180:
 # self.angle = 180
 return
      if (platform.system() == 'Windows'):
 pass
      else:
 self.p.ChangeDutyCycle(2.5 + 10 * self.angle / 180)
         time.sleep(0.02)
 self.p.ChangeDutyCycle(0)
         time.sleep(0.2)
 global currDir
      currDir = 'stop'
 def turnRight(self):
 self.angle -= 5
 if self.angle <= 0:
 return
      if (platform.system() == 'Windows'):
 pass
      else:
 self.p.ChangeDutyCycle(2.5 + 10 * self.angle / 180)
         time.sleep(0.02)
 self.p.ChangeDutyCycle(0)
         time.sleep(0.2)
 global currDir
      currDir = 'stop'
 def checkDirection(self):
 global currDir
 if currDir == 'stop':
 pass
      elif currDir == 'left':
 self.turnLeft()
 elif currDir == 'right':
 self.turnRight()
 def doWork(self):
 print('running steeringSG90 ...')
 if self.gpioFlag == False:
 print('Plase set GPIO by setGPIO()')
 return
      if (platform.system() == 'Windows'):
 pass
      else:
 self.p = GPIO.PWM(self.ServoPin, 50)  # 50HZ
 self.p.start(0)
 self.gpioFlag = False
 self.initCheckSelf()
 while self.working == True:
 # print('...')
 self.checkDirection()
         time.sleep(0.2)
class SteeringSG90Manager(QObject):
 'SG90舵机管理器'
 operate = pyqtSignal()
 def __init__(self):
 super().__init__()
 self.setup()
 self.worker = SteeringSG90Worker()
 self.thread = QThread()
 self.worker.moveToThread(self.thread)
 self.worker.setGPIO(self.servopin)
 self.thread.finished.connect(self.worker.deleteLater)
 self.operate.connect(self.worker.doWork)
 self.thread.start()
 self.operate.emit()
 def __del__(self):
 self.thread.quit()
 self.thread.wait()
 def setup(self):
 'Init device gpio.'
 self.servopin = 21
 if (platform.system() == 'Windows'):
 pass
      else:
 GPIO.setup(self.servopin, GPIO.OUT)  # ,initial=False
 def controlCommand(self,cmd):
 global currDir
 if cmd == 'left':
         currDir = 'left'
 elif cmd == 'right':
         currDir = 'right'


注意,由于我软件编写测试是在Windows平台下PyCharm软件,当测试软件结构性的时候,为方便测试,使用“platform.system()”判断当前运行环境的系统平台。

4、编写界面分离文件CallHomePage.py,内容如下:


from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from ui_HomePage import Ui_HomePage
from DeviceDriver.UltrasonicModule import UltrasonicManager
from DeviceDriver.SteeringSG90Module import SteeringSG90Manager
from PyQt5.QtCore import pyqtSignal,Qt
import platform
if (platform.system()=='Windows'):
 pass
else:
 import RPi.GPIO as GPIO
class HomePage(QWidget,Ui_HomePage):
strSG90 = pyqtSignal(str)   #只有水平方向
 def __init__(self,parent=None):
 super(HomePage, self).__init__(parent)
 self.setupUi(self)
 self.initUI()
 self.initDevice()
def __del__(self):
 if (platform.system() == 'Windows'):
 pass
    else:
 GPIO.cleanup()
 def initUI(self):
 'iniitUI'
 self.resize(800,480)
 #省略部分界面布局的代码,以下就是绑定舵机左右旋转的两个按钮
 self.leftButton_2.clicked.connect(self.buttonSlot)
 self.rightButton_2.clicked.connect(self.buttonSlot)
 def initDevice(self):
 if (platform.system() == 'Windows'):
  pass
 else:
  GPIO.setmode(GPIO.BCM)
 # 初始化SG90舵机
 self.steeringSG90 = SteeringSG90Manager()
 self.strSG90.connect(self.steeringSG90.controlCommand)
def buttonSlot(self):
  '按钮点击分发处理函数'
  sender = self.sender()
  if sender == self.leftButton_2:
  self.strSG90.emit('left')#超声波舵机左转
  elif sender == self.rightButton_2:
  self.strSG90.emit('right')#超声波舵机右转


注意:由于控制舵机时使用的GPIO模式是GPIO.BCM模式,树莓派中的同一个应用程序同时只能使用一种GPIO模式,所以所有驱动都使用的BCM模式。

树莓派管脚的命令如下:


python有没有控制舵机的库 python控制舵机旋转_pwm控制舵机转动角度程序_09


5、编写main程序入口,我在这里新建了一个main_server.py文件,内容如下:


from PyQt5.QtWidgets import *
from CallHomePage import HomePage
import sys

if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainWindow = HomePage()
    mainWindow.show()
    sys.exit(app.exec_())


二、连接测试

实际连接状态如下图:


python有没有控制舵机的库 python控制舵机旋转_python有没有控制舵机的库_10


python有没有控制舵机的库 python控制舵机旋转_树莓派_11


1、将以上代码传到树莓派中,最好目录结构保持一致


python有没有控制舵机的库 python控制舵机旋转_舵机_12


使用python3命令运行我们的main入口,这样我们就可通过点击界面的按钮来控制舵机的转动了。


python有没有控制舵机的库 python控制舵机旋转_树莓派_13


python有没有控制舵机的库 python控制舵机旋转_pwm控制舵机转动角度程序_14

使用舵机控制超声波模块https://www.zhihu.com/video/1193917543478280192

注意:本人树莓派使用的系统是厂家提供的Raspbian系统,里面已经装好了PyQt5的环境了。