提高整个网站权重,网络公司服务,南安网站开发,wordpress wpgo1、简介
智能小车、机械臂、摄像头云台会有多个舵机#xff0c;而微控制器芯片的PWM输出引脚不够的情况下#xff0c;就可以用PCA9685#xff08;16路舵机#xff09;来解决这一问题。
PCA9685是一款I2C总线控制的16通道LED控制器#xff0c;专为红/绿/蓝/琥珀#xff…1、简介
智能小车、机械臂、摄像头云台会有多个舵机而微控制器芯片的PWM输出引脚不够的情况下就可以用PCA968516路舵机来解决这一问题。
PCA9685是一款I2C总线控制的16通道LED控制器专为红/绿/蓝/琥珀RGBA彩色背光应用而优化。每个LED输出都有自己的12位分辨率4096步固定频率单独PWM控制器可在可编程频率下工作典型频率为24 Hz到1526 Hz占空比可调节从0到100以使LED达到特定的亮度值。所有输出的PWM频率都设置为相同。
每个LED输出可以关闭或打开无PWM控制或设置为其单独的PWM控制器值。LED输出驱动器被编程为开漏带有在5V时25mA的电流下沉能力或者是totem极带有在5V时25mA的下沉和10mA的源能力。PCA9685的工作电压范围为2.3V至5.5V输入和输出均可容忍5.5V。LED可以直接连接到LED输出高达25mA5.5V或通过外部驱动器和最少量的离散元件控制更大电流或更高电压的LED。 2、驱动板特性
• PCA9685允许交替的LED输出开启和关闭时间以最小化电流浪涌。每个16个通道的开启和关闭时间延迟可以独立编程。这个特性在PCA9635中不可用。
• PCA9685具有4096个步骤12位PWM的单独LED亮度控制。
• 当在系统中合并多个LED控制器时如果使用PCA9635多个设备之间的PWM脉冲宽度可能会有所不同。PCA9685具有可编程分频器以调整多个设备的PWM脉冲宽度。
• PCA9685具有外部时钟输入引脚可接受用户提供的时钟最大50 MHz代替内部25 MHz振荡器。此功能允许多个设备同步。PCA9635没有外部时钟输入功能。
• 与PCA9635一样PCA9685也具有用于PWM控制的内置振荡器。但是与PCA9635的典型频率97.6kHz相比PCA9685用于PWM控制的频率可调节约为24 Hz至1526 Hz。这允许使用PCA9685与外部电源控制器。所有位都以相同的频率设置。
• LEDn输出引脚的上电复位POR默认状态在PCA9685的情况下为LOW。而对于PCA9635则为HIGH。
• 所有PWM输出线上都放一个220欧姆系列电阻器来保护他们并能轻易的驱动LED。
3、多驱动板级联
地址选择引脚使你可以把62个驱动板挂在单个12C总线上总共有992路PWM输出级联的每个驱动板都需要有一个唯一的访问地址。每个驱动板的初始I2C地址是0×40可以通过右上角的跳线修改I2C地址。用焊锡将一个跳线连上就表示一个二进制数字“1”。有6个地址控制脚通过这些引脚可以控制设备的i2c地址。7位的I2C地址为0x40 A5:A0 Board 0: Address 0x40 Offset binary 00000 (默认) Board 1: Address 0x41 Offset binary 00001 (如上图接上A0) Board 2: Address 0x42 Offset binary 00010 (接上A1) Board 3: Address 0x43 Offset binary 00011 (接上A0和A1) Board 4: Address 0x44 Offset binary 00100 (接上A2)
4、外部电源接入
大多数的舵机设计电压都是在5~6V尤其在多个舵机同时运行时跟需要有大功率的电源供电。如果直接使用5V引脚直接为舵机供电会出现一些难以预测的问题所以建议你能有个合适的外部电源为驱动板供电。中间上面的绿色接线柱是提供外围输入电压舵机后面提示外围输入供电电压不要超过6V。V线上放置一个大电容(在某些场合你会需要) 外围输入最大电压取决于这个10V1000uf的电容。 PCA9685-16路舵机是一个采用IIC通信内置了PWM驱动器和一个时钟这个意味着这将和TLCG940系列有很大不同你不需要不断发送信号占用你的单片机。它是5V的兼容这意味你还可以用3.3V单片机控制并且安全地驱动到6V输出(当你想要控制白色或蓝色指示灯用3.4正电压也是可以的)。约1.6Khz可调频PWM输出为步进电机准备输出12位分辨率可配置的推拉输出或开路输出输出使能引脚能够快速禁用所有输出。
这个地方说明书上的意思我重新给同学们解释下。如果不仔细思考理解可能很多同学有点晕。
VCC和V这两个地方是有区别的。VCC是给PCA9685芯片供电的电压3-5V。而V是给舵机供电的电压。那么问题来了1是扩展板好几个地方都有V哪里是输入哪里是输出2是V的那个一会最大6V一会6-10V是什么意思呢
扩展板要给舵机供电首先要有电压输入如果仅接VCC无法提供输出电压。要提供输出电压必须接上左图的绿色接线柱这个输入电压范围为6-10V然后V的所有输出电压就有了。这个输出的电压都是来自绿色接线柱的输入电压输入多少输出就是多少但是为了保护舵机扩展板提供稳压保护即便输入的电压有9V它输出的电压最大不超过6.5V因为大多数舵机的工作电压5-6V。所以如果要带的舵机额定电压需要6.5V以上就单独供电把PWM信号线接扩展板即可。
这里我再扩展下介绍输出电压、电流与负载的关系。这里我可以拿手机电池和手机充电器给大家举例。如果手机电池的的输入电压为5V那么充电器的输出电压一定要5V才行不能大也不能小。如果输入电压大了不烧坏手机说明内部有保护的稳压电路小了更不行芯片不能工作。而充电器提供的输出电流则越大越好当然价格也高这个完全看负载所需的电流只要电池所需要的输入电流小于等于充电器提供的输出电流都可以。但是要是充电器输出电流小于电池需要的输入电流则不行它有一个阈值低于阈值充不进去电高于阈值则充电比较慢也能充。舵机也是一样所以最好是满足负载所需的电压和电流才行。
我们也做了很多实验了树莓派或其他芯片提供的输出电压往往可以满足负载但输出电流较弱驱动大电流的设备往往需要单独供电。
5、电路原理图 6、PCA9685的驱动
该模块仍然采用IIC总线可以查看其地址为0x40。 from __future__ import division
import logging
import time
import math# Registers/etc:
PCA9685_ADDRESS 0x40
MODE1 0x00
MODE2 0x01
SUBADR1 0x02
SUBADR2 0x03
SUBADR3 0x04
PRESCALE 0xFE
LED0_ON_L 0x06
LED0_ON_H 0x07
LED0_OFF_L 0x08
LED0_OFF_H 0x09
ALL_LED_ON_L 0xFA
ALL_LED_ON_H 0xFB
ALL_LED_OFF_L 0xFC
ALL_LED_OFF_H 0xFD# Bits:
RESTART 0x80
SLEEP 0x10
ALLCALL 0x01
INVRT 0x10
OUTDRV 0x04logger logging.getLogger(__name__)class PCA9685(object):PCA9685 PWM LED/servo controller.def __init__(self, addressPCA9685_ADDRESS, i2cNone, **kwargs):Initialize the PCA9685.# Setup I2C interface for the device.if i2c is None:import Adafruit_GPIO.I2C as I2Ci2c I2Cself._device i2c.get_i2c_device(address, **kwargs)self.set_all_pwm(0, 0)self._device.write8(MODE2, OUTDRV)self._device.write8(MODE1, ALLCALL)time.sleep(0.005) # wait for oscillatormode1 self._device.readU8(MODE1)mode1 mode1 ~SLEEP # wake up (reset sleep)self._device.write8(MODE1, mode1)time.sleep(0.005) # wait for oscillatordef set_pwm_freq(self, freq_hz):Set the PWM frequency to the provided value in hertz.prescaleval 25000000.0 # 25MHzprescaleval / 4096.0 # 12-bitprescaleval / float(freq_hz)prescaleval - 1.0logger.debug(Setting PWM frequency to {0} Hz.format(freq_hz))logger.debug(Estimated pre-scale: {0}.format(prescaleval))prescale int(math.floor(prescaleval 0.5))logger.debug(Final pre-scale: {0}.format(prescale))oldmode self._device.readU8(MODE1);newmode (oldmode 0x7F) | 0x10 # sleepself._device.write8(MODE1, newmode) # go to sleepself._device.write8(PRESCALE, prescale)self._device.write8(MODE1, oldmode)time.sleep(0.005)self._device.write8(MODE1, oldmode | 0x80)def set_pwm(self, channel, on, off):Sets a single PWM channel.self._device.write8(LED0_ON_L4*channel, on 0xFF)self._device.write8(LED0_ON_H4*channel, on 8)self._device.write8(LED0_OFF_L4*channel, off 0xFF)self._device.write8(LED0_OFF_H4*channel, off 8)def set_all_pwm(self, on, off):Sets all PWM channels.self._device.write8(ALL_LED_ON_L, on 0xFF)self._device.write8(ALL_LED_ON_H, on 8)self._device.write8(ALL_LED_OFF_L, off 0xFF)self._device.write8(ALL_LED_OFF_H, off 8)
一共这个舵机控制类就4个函数init为初始化函数set_pwm_freq设置频率set_pwm控制单个舵机set_all_pwm控制全部舵机。
7、实验代码与现象
1我手头没有多个舵机先用多个LED流水灯做实验多个舵机的实验代码我也放到最后回头拿到机械臂之后我再想办法连接到树莓派上面。因为这个PCA9685的输出最大电压为6.5V。机械臂上有的舵机电压可能要大于6.5V。我回头要实验看下这个9685能否给机械臂提供供电
2我们这边要控制多个LED的灯光可以多个灯不同时亮暗采用多线程实现。
import pca9685
import time
import threadingLed_pwm pca9685.PCA9685(busnum1)
Led_pwm.set_pwm_freq(600) # 设置频率为60HZdef LED0_ctrl():for i in range(0,5000,10):Led_pwm.set_pwm(0,0,i)time.sleep(0.01)def LED1_ctrl():for i in range(0,3000,10):Led_pwm.set_pwm(1,0,i)time.sleep(0.01)def LED2_ctrl():for i in range(4000,0,-20):Led_pwm.set_pwm(2,0,i)time.sleep(0.03)
try:while True:t0threading.Thread(targetLED0_ctrl) # 多线程t1threading.Thread(targetLED1_ctrl)t2threading.Thread(targetLED2_ctrl)t0.start() # 开启线程t1.start() t2.start() t0.join()t1.join()t2.join()
except KeyboardInterrupt:exit()3Python有个专门的舵机旋转角度控制函数我们安装这些库来调用。
# sudo pip install adafruit-circuitpython-pca9685 # sudo pip install adafruit-circuitpython-servokit
from adafruit_pca9685 import PCA9685
from board import SCL, SDA
import busio
from adafruit_motor import servoi2c_bus busio.I2C(SCL, SDA)
pwm PCA9685(i2c_bus) # 使用默认地址初始化PWM设备
pwm.frequency 50 # 将频率设置为50 Hz
servo_12 servo.Servo(pwm.channels[12]) # 指定第12通道的舵机从0开始
servo_15 servo.Servo(pwm.channels[15]) # 指定第15通道的舵机print(Moving servo on channel 0, press Ctrl-C to quit...)
servo_12.angle 90
servo_15.angle 90
while True:# 伺服电机转动最小角度和最大角度servo_12.angle 0servo_15.angle 0time.sleep(1)servo_12.angle 180servo_15.angle 180time.sleep(1)
可以接舵机试试控制角度非常方便。