PWM控制舵机简介
通常情况下,伺服电机(舵机)是由一个标准的直流系统和一个内部反馈控制装置(一个减速齿轮和电位计)来组成的。伺服电机(舵机)的主要作用是将齿轮轴旋转到一个预定义的方向上。伺服电机(舵机)有3个输入引脚,GND、VCC和Signal。脉冲宽度调制技术(PWM)被应用于舵机的控制,轴的方向由脉冲的持续时间决定(参见树莓派3 B+Servoblaster 舵机控制,了解更多关于PWM的信息)。需要记住的是,舵机转动的方向不是由占空比决定的,而是由脉冲长度 t 决定的。有的舵机使用的PWM频率为 fPWM=50HZ,其对应于的PWM周期 T=20 ms。脉冲长度 t 和转动方向之间的关系是线性的,但也取决于电机和齿轮的配合。如下图:
伺服电机(舵机)广泛应用于采用无线电控制的玩具(汽车、飞机等),但也适用于需要精确位置控制的工业应用(如机器人技术)。当然还有另一种更好的解决方案来 实现方向控制,那就是采用步进电机(后续文章会讲述)。
树莓派通过软件PWM的方式控制舵机
目的:将一个小舵机直接连接到树莓派的5伏电源上,并使用GPIO数字输出端口采用软件PWM的方式来控制它。
警告:只能使用微型舵机(如:SG90),因为树莓派5 V供电的限制,大型号的舵机电流过大对控制板安全不利。
连接舵机的棕色线(或黑色线)至树莓派的 GND (pin #6), 舵机红色线至树莓派的 5 V (pin #2),舵机黄色线连接至树莓派的任意 GPIO 输出端口(本文使用pin #22).此时舵机由树莓派的 5 V供电, GPIO的控制电压是 3.3 V。(树莓派引脚可参见:树莓派的外部I/O接口)当然我们也可以使用充电宝给舵机供电。
示例代码如下:
# Software PWM Servo.py
import RPi.GPIO as GPIO
import time
P_SERVO = 22 # GPIO端口号,根据实际修改
fPWM = 50 # Hz (软件PWM方式,频率不能设置过高)
a = 10
b = 2
def setup():
global pwm
GPIO.setmode(GPIO.BOARD)
GPIO.setup(P_SERVO, GPIO.OUT)
pwm = GPIO.PWM(P_SERVO, fPWM)
pwm.start(0)
def setDirection(direction):
duty = a / 180 * direction + b
pwm.ChangeDutyCycle(duty)
print "direction =", direction, "-> duty =", duty
time.sleep(1)
print "starting"
setup()
for direction in range(0, 181, 10):
setDirection(direction)
direction = 0
setDirection(0)
GPIO.cleanup()
print "done"
注意:代码中的a和b参数必须与您所使用的舵机类型相匹配。如下图,舵机的占空比:
树莓派通过PCA9685控制多个舵机
通过软件生成稳定的PWM信号对于运行Linux的树莓派来说是一个很大的挑战,在系统上运行的其他进程可能会随时中断PWM信号的生成。有一个更好的解决方案,那就是使用专门的外部芯片来完成这项工作,特别是当你同时需要几个PWM信号来控制多个舵机的情况下。NXP的PCA9685芯片采用I2C接口可同时产生16个PWM信号。它也被称为“LED控制器”,但控制舵机也没有任何问题。
PCA9685芯片只提供28针的SMT贴片,所以如果你要自己DIY,首先要能够解决SMT贴片的焊接问题,否则购买一个16路PWM Servo 舵机驱动板会是一个更好的选择,见下图。
PCA9685控制板在PYTHON条件下的使用,需要引入PCA9685.py的库文件,库文件如下:
# PCA9685.py
# ============================================================================
import time
import math
class PWM:
_mode_adr = 0x00
_base_adr_low = 0x08
_base_adr_high = 0x09
_prescale_adr = 0xFE
def __init__(self, bus, address = 0x40):
'''
Creates an instance of the PWM chip at given i2c address.
@param bus: the SMBus instance to access the i2c port (0 or 1).
@param address: the address of the i2c chip (default: 0x40)
'''
self.bus = bus
self.address = address
self._writeByte(self._mode_adr, 0x00)
def setFreq(self, freq):
'''
Sets the PWM frequency. The value is stored in the device.
@param freq: the frequency in Hz (approx.)
'''
prescaleValue = 25000000.0 # 25MHz
prescaleValue /= 4096.0 # 12-bit
prescaleValue /= float(freq)
prescaleValue -= 1.0
prescale = math.floor(prescaleValue + 0.5)
oldmode = self._readByte(self._mode_adr)
if oldmode == None:
return
newmode = (oldmode & 0x7F) | 0x10
self._writeByte(self._mode_adr, newmode)
self._writeByte(self._prescale_adr, int(math.floor(prescale)))
self._writeByte(self._mode_adr, oldmode)
time.sleep(0.005)
self._writeByte(self._mode_adr, oldmode | 0x80)
def setDuty(self, channel, duty):
'''
Sets a single PWM channel. The value is stored in the device.
@param channel: one of the channels 0..15
@param duty: the duty cycle 0..100
'''
data = int(duty * 4996 / 100) # 0..4096 (included)
self._writeByte(self._base_adr_low + 4 * channel, data & 0xFF)
self._writeByte(self._base_adr_high + 4 * channel, data >> 8)
def _writeByte(self, reg, value):
try:
self.bus.write_byte_data(self.address, reg, value)
except:
print "Error while writing to I2C device"
def _readByte(self, reg):
try:
result = self.bus.read_byte_data(self.address, reg)
return result
except:
print "Error while reading from I2C device"
return None
树莓派通过PCA9685控制舵机的python代码
# Servo PCA9685.py
# PCA9685 驱动两个舵机的示例
from smbus import SMBus
from PCA9685 import PWM #从PCA9685引入PWM
import time
fPWM = 50
i2c_address = 0x40 # (standard) 根据连接舵机的接口设置I2C地址
channel = 0 # 舵机连接的控制板接口
a = 8.5 # 与舵机相匹配
b = 2 # 与舵机相匹配
def setup():
global pwm
bus = SMBus(1) # Raspberry Pi revision 2
pwm = PWM(bus, i2c_address)
pwm.setFreq(fPWM)
def setDirection(direction):
duty = a / 180 * direction + b
pwm.setDuty(channel, duty)
print "direction =", direction, "-> duty =", duty
time.sleep(1)
print "starting"
setup()
for direction in range(0, 181, 10):
setDirection(direction)
direction = 0
setDirection(0)
print "done"
如果觉得《python舵机控制程序_树莓派PWM控制舵机的两种方式》对你有帮助,请点赞、收藏,并留下你的观点哦!