失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > python舵机控制程序_树莓派PWM控制舵机的两种方式

python舵机控制程序_树莓派PWM控制舵机的两种方式

时间:2022-06-06 23:39:30

相关推荐

python舵机控制程序_树莓派PWM控制舵机的两种方式

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控制舵机的两种方式》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。