当前位置: 首页 > news >正文

嵌入式人工智能(45-基于树莓派4B的扩展板-舵机驱动板PCA9685)

1、简介

智能小车、机械臂、摄像头云台会有多个舵机,而微控制器芯片的PWM输出引脚不够的情况下,就可以用PCA9685(16路舵机)来解决这一问题。

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输出(高达25mA,5.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, address=PCA9685_ADDRESS, i2c=None, **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_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)

一共这个舵机控制类就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(busnum=1)
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:t0=threading.Thread(target=LED0_ctrl)  # 多线程t1=threading.Thread(target=LED1_ctrl)t2=threading.Thread(target=LED2_ctrl)t0.start()   # 开启线程t1.start() t2.start() t0.join()t1.join()t2.join()
except KeyboardInterrupt:exit()

(3)Python有个专门的舵机旋转角度控制函数,我们安装这些库来调用。

# 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)

可以接舵机试试,控制角度非常方便。

相关文章:

嵌入式人工智能(45-基于树莓派4B的扩展板-舵机驱动板PCA9685)

1、简介 智能小车、机械臂、摄像头云台会有多个舵机,而微控制器芯片的PWM输出引脚不够的情况下,就可以用PCA9685(16路舵机)来解决这一问题。 PCA9685是一款I2C总线控制的16通道LED控制器,专为红/绿/蓝/琥珀&#xff…...

【数据结构与算法】建立多个栈的三种方案的优缺点分析

在一个算法中需要建立多个栈时可以选用以下三种方案之一,试问这三方案相比各有什么优缺点? (1)分别用多个顺序存储空间建立多个独立的顺序栈。 (2)多个栈共享一个顺序存储空间。 (3)…...

DjangoRF-14-创建request子应用

注意,本应该是requests模块,为了区分,避免错误,用request 1、进入apps,创建request django-admin startapp request 2、因为只发送请求,没有数据库相关,不需要model。 3、进行序列化 from rest_framework …...

SOMEIP_ETS_005:检查字节序

测试目的: 验证DUT在发送和接收参数时对字节序的处理能力。 描述 本测试用例旨在检验DUT在处理具有不同字节序的参数时,是否能够正确地发送和接收数据,并确保返回的UINT32值是传入的两个参数(UINT8和UINT16)的和。 …...

为什么要对医疗器械进行网络安全评估?

对医疗器械进行网络安全评估的原因主要有以下几点: 一、保障患者安全 直接关联患者健康:医疗器械与患者的生命健康直接相关,任何网络安全漏洞都可能导致设备被非法控制或数据泄露,进而威胁患者的生命安全。例如,黑客可…...

沃尔玛1P账号的强悍作用重要反映在那些方面?——WAYLI威利跨境助力商家

沃尔玛作为全球最大的零售商之一,其品牌影响力非常强大。商家通过入驻沃尔玛商超并开设1P账号,能够借助沃尔玛的品牌影响力来提升自身的品牌知名度和美誉度。这种品牌背书的效应,有助于商家吸引更多的消费者关注和购买自己的产品。 一、沃尔玛…...

学习python你不能不知道的几个接单平台!实现如月上万不是梦

学Python后,寻找兼职平台是一个很好的实践和提升技能的方式。以下是一些比较推荐的Python兼职平台: 国内平台 程序员客栈 网址:https://www.proginn.com介绍:程序员客栈是中国非常领先的自由工作平台,为中高端程序员、…...

Golang面试题三(map)

1.map底层实现 由图看出,其实map的底层结构体是hmap,同时hmap里面维护着若干个bucket数组(即桶数组)。bucket数组中每个元素都是bmap结构的,bmap中存储着8个key-value的键值对,如果是满了的话,当…...

[windows10]win10永久禁用系统自动更新操作方法

WinR打开运行 输入regedit打开注册表 点击确定打开注册表 按照如下路径找到UX 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings 在空白处点击鼠标右键,新建选择DWORD,然后重命名为FlightSettingsMaxPauseDays 双击FlightSet…...

《西行取经:大学生编程之路的禅悟与陷阱规避2》

《西行取经:大学生编程之路的禅悟与陷阱规避2》 阿弥陀佛,贫僧唐僧,虽身处古代,心却向往智慧之光。观今世大学生于编程之途,犹如我等西天取经,路途遥远且布满荆棘。今欲以吾之“取经”心得,为尔…...

JVM从入门到放弃

前言:关于JVM,其实有很多大厂开发了不同版本的JVM,比较知名的有:Sun HotSpot VM、BEA JRockit VM、IBM J9 VM、 Azul VM、 Apache Harmony、 Google Dalvik VM、 Microsoft JVM等等。现在使用的比较多的JDK8版本就是Sun HotSpot V…...

中国地面太阳总辐射逐日资料

数据内容 数据包含站点总辐射辐照度日数据 数据样例 Station_ID_CStaion_NameYearMonDayV1431154832寿光2023116.285754832寿光2023127.778354832寿光2023138.374454832寿光2023147.19154832寿光2023157.506254832寿光2023168.505254832寿光2023179.822154832寿光20231810.0…...

微商来客小程序系统源码分享

微商来客小程序系统源码,这是最新的V7.5.8版本微商来客小程序快速开发系统源码,可以无限开发生成小程序,支持快速生成微信小程序,支付宝小程序,百度小程序,QQ小程序,头条/抖音小程序。能创建的小…...

Java面试题--JVM大厂篇之Parallel GC与其他垃圾回收器的对比与选择

目录 引言: 正文: 结束语: 引言: Java工程师们,当我们在谈论JVM性能优化时,垃圾回收器(GC)无疑是一个绕不开的话题。而在所有的垃圾回收器中,Parallel GC无疑是一个备受关注的角色。今天,我们就来一探究…...

十分钟带你速通 Vue 组件

自定义组件 组件是可复用的 Vue 实例,在开发过程中,我们可以把重复用到的功能封装成自定义组件,达到便捷开发的目的。 组件的组织 通常一个应用会以一棵嵌套的组件树的形式来组织: 你可能会有头部导航、内容区、侧边栏等组件&a…...

基于RK3588+AI支持能源在线监测系统应用的AIOT产品方案

支持能源在线监测系统应用的AIOT产品方案 近年来,智慧能源行业受益于国家政策扶持、市场需求拉动和先进技术支撑呈现出了蓬勃发展态势。助推智慧能源发展,打造了支持能源在线监测系统应用的AIOT产品方案。 能源在线监测系统的市场潜力 随着社会经济的飞…...

山东大学考研机试题——整数序列

题目描述 传送门——AcWing 3717. 整数序列 - AcWing 很多整数可以由一段连续的正整数序列(至少两个数)相加而成,比如 2534567121325345671213。 输入一个整数 N,输出 N 的全部正整数序列,如果没有则输出 NONE。 输…...

一口酒一口水,不宜喝醉

一口酒一口水。这样交替着喝可以冲淡血液里的酒精浓度,但要注意不是往酒里兑水。 小口喝。每小时分解酒精的能力有限,如果超过负荷,血液里乙醛浓度会增加,引起酒醉。因此,喝酒时要尽量小口慢慢喝,给分解酒精…...

AI6-PPOCRLabel带GPU训练

一、移动PPOCRLabel 从anconda安装目录中找到PPOCRLabel文件夹,移动到PaddleOCR-release-2.8文件夹下 二、启动PPOCCRLabel cmd命令行进入paddle_py38环境,使用PPOCRLabel --lang ch来启动PPOCRLabel 三、打开图片文件夹自动标志 四、标签数据整理 …...

Unity四元数线性插值Lerp

inline glm::quat Lerp(glm::quat quat1, glm::quat quat2, float t)//普通插值 {t glm::clamp(t, 0.0f, 1.0f);return glm::normalize(quat1*(1-t)quat2*t); }...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...

【2025年】解决Burpsuite抓不到https包的问题

环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...

微信小程序云开发平台MySQL的连接方式

注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...

JVM 内存结构 详解

内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: ​ 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...