一、安装 Adafruit-PCA9685
sudo pip install adafruit-pca9685
二、引入包
import Adafruit_PCA9685
三、内部方法
class PCA9685(object):
"""PCA9685 PWM LED/servo controller."""
def __init__(self, address=PCA9685_ADDRESS, i2c=None, **kwargs):
"""Initialize the PCA9685."""
# Setup I2C interface for the device.
if i2c is None:
import Adafruit_GPIO.I2C as I2C
i2c = I2C
self._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 oscillator
mode1 = self._device.readU8(MODE1)
mode1 = mode1 & ~SLEEP # wake up (reset sleep)
self._device.write8(MODE1, mode1)
time.sleep(0.005) # wait for oscillator
def set_pwm_freq(self, freq_hz):
"""Set the PWM frequency to the provided value in hertz."""
prescaleval = 25000000.0 # 25MHz
prescaleval /= 4096.0 # 12-bit
prescaleval /= float(freq_hz)
prescaleval -= 1.0
logger.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 # sleep
self._device.write8(MODE1, newmode) # go to sleep
self._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_L+4*channel, on & 0xFF)
self._device.write8(LED0_ON_H+4*channel, on >> 8)
self._device.write8(LED0_OFF_L+4*channel, off & 0xFF)
self._device.write8(LED0_OFF_H+4*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)
各个通道的ON和OFF寄存器
总共16个通道,每个通道都有 LEDX_ON_L、LEDX_ON_H、LEDX_OFF_L、LEDX_OFF_H 四个寄存器。
系统中有一个12位的计数ACK,ACK根据PRE_SCALE寄存器设置的周期进行增加,没增加一次就会和上述四个寄存器对比:
当发现 ACK == LEDX_ON_H[3:0]:LEDX_ON_L 时,X通道输出高电平;
当发现 ACK == LEDX_OFF_H[3:0]:LEDX_OFF_L 时,X通道输出低电平。
set_pwm要注意on和 off的赋值
on寄存器为0,off寄存器存入数值
on寄存器存入数值,off寄存器为0
三、用法
3.1 创建一个PWM实例
pwm = Adafruit_PCA9685.PCA9685()
# 地址默认为这个 address=PCA9685_ADDRESS
# 如果修改了模块上的地址,则需要修改。
3.2 设置频率
pwm.set_pwm_freq(50)
3.3 更改占空比
# 单独通道修改
pwm.set_pwm(channel,on,off)
# 一次性修改
set_all_pwm(self, on, off):
3.4 实列
import Adafruit_PCA9685
import time
pwm = Adafruit_PCA9685.PCA9685()
def set_servo_angle(channel, angle): #输入角度转换成12^精度的数值
date=4096*((angle*11)+500)/20000 #进行四舍五入运算 date=int(4096*((angle*11)+500)/(20000)+0.5)
pwm.set_pwm(channel, 0,int(date))
pwm.set_pwm_freq(50)
print('Moving servo on channel x, press Ctrl-C to quit...')
while True:
# Move servo on channel O between extremes.
channel=int(input('pleas input channel:'))
angle=int(input('pleas input angle:'))
set_servo_angle(0, angle)
#time.sleep(1)
四、PCA9685 模块的一些小细节
4.1 7位的I2C地址为:0x40 + A5:A0,A5到A0如果不做任何处理的话是0,想要把哪一位置1就把那个引脚焊到一起。生成实列的时候需要修改默认值。另外用i2cdetect检测出还有一个0x70地址一直存在,这是一个通用地址,可以给所有从机下达指令。
4.2 模块有一个OE反使能脚,这个引脚低电平使能,不接的话模块内部默认已经接地使能了,所以正常使用可以不接。