元器件 · 驱动器
PCA9685 舵机驱动板
PCA9685 只占两个引脚,通过 I²C 驱动 16 路舵机或 PWM 输出——这是驱动机械臂或大量舵机、又不拖累单片机的标准做法。
它是什么
PCA9685 是舵机倍增器。单片机硬件 PWM 没几路,机械臂六舵机——别说六足十八舵机——转眼脚和定时器全没。这小板子接管:硬件生成 16 路独立 PWM 信号,两根 I²C 线全指挥。多舵机机器人背后都是它。
工作原理
你通过 I²C 与 PCA9685 通信——同样那两个引脚(SCL/SDA)还能挂其它传感器。你为整颗芯片设置一个 PWM 频率(玩具级舵机是 50 Hz),再设置每个通道的脉宽来决定对应舵机的位置。因为这 16 路信号都由硬件保持,单片机只要发出“3 号通道 → 1.5 ms”然后就完事了,自己根本不用再去位操作生成时序。正是这一点让 16 个舵机同时动作时每一个都依然平滑。脉宽与角度的对应思路,和SG90 舵机那一页讲的是同一个。
什么时候用它
机器人舵机比单片机 PWM 脚多,或舵机要稳如磐石时拿 PCA9685:
- 机械臂——几关节舵机齐动(配逆解)。
- 六足 / 四足——十几条腿的舵机。
- 云台相机——单片机定时器留给别的活。
如果只有单个扫描舵机——比如避障车上的超声波扫描头——你不需要它;单片机直接驱动一路舵机就够了。
接线与坑
- **两路电源。**逻辑(VCC)走单片机;舵机电源走 V+ 端子。16 舵机电流绝不走 Arduino 5 V。
- **V+ 要按堵转电流选,不要按空闲电流。**16 个舵机一起动作能拉好几个安培;电源选小了就会电压下垂,整块板子跟着抖。
- 级联地址唯一,焊跳线设。
- V+ 并电容,吸收舵机启动电流尖峰。
引脚
三组连接:接单片机的控制排针,十六组舵机排针,和绝不能混的电源端子。
| 组 | 引脚 | 作用 |
|---|---|---|
| 控制 | VCC | 只供逻辑,单片机 3.3 V 或 5 V。不是舵机电源 |
| 控制 | GND | 地——必须和单片机、舵机电源都共地 |
| 控制 | SCL | I²C 时钟 |
| 控制 | SDA | I²C 数据 |
| 控制 | OE | 输出使能,低有效。悬空被拉低,输出开 |
| 电源 | V+(螺丝端子) | 舵机电流。常见转接板最高 6 V |
| 输出 | 0–15 | 每组三针:PWM 信号、V+、GND——标准舵机顺序 |
| 地址 | A0–A5(焊盘) | 六跳线选 I²C 地址,默认 0x40 |
这块板上后果最严重的一条事实是:**VCC 和 V+ 是两条不同的电源轨。**VCC 供芯片,V+ 供舵机。把它们短接在一起,就会让舵机的堵转电流流过单片机的稳压器,这是让 Arduino 欠压复位最快的办法。
接到 Arduino
| PCA9685 | Arduino Uno | ESP32 | 说明 |
|---|---|---|---|
| VCC | 5 V | 3.3 V | 几毫安——只逻辑 |
| GND | GND | GND | 还和舵机电源地共地 |
| SDA | A4 | GPIO 21 | 板上 10 kΩ 上拉现成 |
| SCL | A5 | GPIO 22 | 同上 |
| V+ | 不接 Arduino | 不接 ESP32 | 独立 5–6 V 电源,按堵转配 |
| OE | 悬空 | 悬空 | 或一脚驱动,一次灭全部输出 |
OE 比它看起来有用得多。把它拉高,就在硬件层面瞬间关掉全部十六路输出,不需要任何 I²C 事务。对一条会因重力而掉下来的机械臂来说,这就是真正的急停,而且即使你的代码已经卡死也照样有效。
舵机电源配多大
大多数 PCA9685 项目都是在这里翻车的,而这道算术并不难。
一个玩具级舵机大致消耗:
| 舵机 | 空闲 | 转动无负载 | 堵转 |
|---|---|---|---|
| SG90(9 g) | 约 10 mA | 约 150–250 mA | 约 650 mA |
| MG90S(金属齿) | 约 10 mA | 约 250–400 mA | 约 800 mA |
| MG996R(标准) | 约 10 mA | 约 500–900 mA | 约 2.5 A |
小臂四 SG90 齐动舒服 1 A,全堵一起峰值近 2.6 A——臂撞自家框架正这样。1 A 手机充电器不行。按所有舵机同时堵转配,至少所有转动加一堵转。
电源选小了之后的症状既鲜明又让人困惑:舵机抖动,板子可能复位,看起来像 I²C 或代码的问题。并不是。在机械臂运动时把万用表接到 V+ 上,看着它往下掉。
**V+ 并电容。**470–1000 µF 量级,贴端子。持续堵转扛不住——1000 µF 供 1 A 每毫秒掉一伏——但舵机启动瞬间尖峰吸收,耦合进逻辑轨的就是它。
PWM 到底怎么生成
两数懂了舵机驱动问题都好诊。
芯片内 25 MHz 振荡器分频:
prescale = round(25000000 / (4096 x frequency)) - 1
玩具级舵机要的 50 Hz,对应 round(25000000 / 204800) - 1 = 121。
每周期再分 4096 步(12 位)。50 Hz 周期 20 ms,单步 20 ms / 4096 = 4.88 µs。关心的舵机脉宽变写的数:
| 脉宽 | 含义 | 50 Hz 计数 |
|---|---|---|
| 1.0 ms | 行程一头 | 205 |
| 1.5 ms | 居中 | 307 |
| 2.0 ms | 另一头 | 410 |
由此直接得出两个结论。第一,舵机整个 180° 行程大约有 205 个计数,也就是每度还不到一个计数——所以限制玩具级舵机精度的不是 PCA9685 的 12 位分辨率,而是舵机自己的死区。第二,预分频器只能在芯片处于睡眠模式时写入,这就是每个库在改频率时都要先切换 MODE1 的原因。
振荡器不是精确 25 MHz
实际板子的振荡频率会偏离标称值几个百分点,而且每块板各不相同。如果你的舵机在行程两端都系统性地达不到指令角度,解决办法不是去凑脉宽,而是去测量并校正时钟:
pwm.begin();
pwm.setOscillatorFrequency(26075000); // measured, not the 25 MHz nominal
pwm.setPWMFreq(50);
先指令 50 Hz,用示波器或逻辑分析仪接任意一路输出,读出真实周期。把标称的 25 MHz 按指令频率与实测频率之比缩放。每块板做一次,把算出的数字写在注释里。
能跑的最小代码
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);
// Per-servo calibration. These are NOT universal — measure your own.
const int SERVO_MIN = 150; // counts at one end stop
const int SERVO_MAX = 600; // counts at the other
int countsFor(int degrees) {
return map(constrain(degrees, 0, 180), 0, 180, SERVO_MIN, SERVO_MAX);
}
void setup() {
pwm.begin();
pwm.setOscillatorFrequency(25000000); // replace with your measured value
pwm.setPWMFreq(50); // hobby servos want 50 Hz
delay(10);
}
void loop() {
for (int a = 0; a <= 180; a += 5) { // sweep, don't jump
pwm.setPWM(0, 0, countsFor(a));
delay(20);
}
for (int a = 180; a >= 0; a -= 5) {
pwm.setPWM(0, 0, countsFor(a));
delay(20);
}
}
SERVO_MIN/SERVO_MAX 这两个常量就是标定值,而且每台舵机都不同——甚至同一袋里同一型号的两台也不一样。找它们的方法是从 307 开始慢慢往外加,舵机发出嗡嗡声却不动的那个点就停下来,那说明它正顶着自己的限位、白白消耗堵转电流,边界就在那里。
还要注意应该用逐步扫描而不是跳变。setPWM 会瞬间改变指令位置,舵机会试图以全速赶到,在机械臂上就意味着一次剧烈的运动和一次电流尖峰。把指令一步步走过去,就是穷人版的运动曲线,即便在测试代码里也值得这么做。
级联
每板六焊盘 A0 到 A5,0x40 起 64 地址。每板桥不同组合:
| 桥接 | 地址 |
|---|---|
| 无 | 0x40 |
| A0 | 0x41 |
| A1 | 0x42 |
| A0 + A1 | 0x43 |
| A5 | 0x60 |
文档最大 62 板——0x70 是 I²C 广播保留,所以不满 64。实践极限早得多:62 板 992 舵机,供电是比 bus 大得多的工程。
级联时要留意:每块板都自带 10 kΩ 的 I²C 上拉电阻,而它们是并联的。十块板就变成 1 kΩ,对 5 V 总线来说已经偏重了。超过几块板之后,就把除一块之外所有板上的上拉跳线都割掉。
故障排查
| 现象 | 可能原因 | 解决 |
|---|---|---|
| 纹丝不动 | V+ 无舵机电源 | V+ 独立轨;VCC 只供芯片 |
| 舵机一直抖 | 负载下电源电压下垂 | V+ 按堵转电流选;加 470–1000 µF 电容 |
| 几路齐动才抖 | 同上,边缘 | 同上——动时万用表量 V+ |
| 某舵机嗡嗡发热 | 指令超限位 | 收那通道 SERVO_MIN/SERVO_MAX |
| 角度系统性地偏短 | 振荡器不是精确的 25 MHz | 测出真实输出频率,调用 setOscillatorFrequency |
| 总线上找不到板子 | 地址错了,或者没有逻辑电源 | 扫描总线;检查 VCC,以及地址跳线是否与代码一致 |
| 两板只应一板 | 都在默认 0x40 |
桥地址跳线每板唯一 |
| 臂一动 Arduino 复位 | 舵机电流过板子 | V+ 独立电源,只共地 |
| I²C 好输出死 | OE 拉高 |
OE 悬空或拉低 |
PCA9685 还是单片机直驱 PWM?
| 直驱 PWM 脚 | PCA9685 | |
|---|---|---|
| 通道 | Uno 上 6 路,Servo 库还会占用一个定时器 |
每板 16 路,一条总线可挂 62 块板 |
| 占脚 | 每舵机一脚 | 全部两脚 |
| 时序 | 由单片机生成——主循环一忙就抖 | 由硬件生成——无论你的代码在做什么都稳定 |
| 电源路径 | 随便接,经常错 | 专用 V+ 端子把正解摆明面 |
| 额外成本 | 无 | 几块钱加 I²C 地址 |
一个诚实的分界线是:**只有一两个舵机,就直接驱动。**避障车上的扫描传感器头不需要这块板。三个及以上,或者任何对平滑度有要求的舵机,PCA9685 就立刻值回票价——不是因为引脚数,而是因为单片机不再负责计时。用 Servo 库驱动的舵机,只要主循环一停顿就会抽搐;用 PCA9685 驱动的则不会。
探索关联图谱
用到它的搭建
包含 PCA9685 舵机驱动板 的项目、学习路线和模拟器。
问题
PCA9685 舵机驱动板 常见问题
PCA9685 是什么?
PCA9685 是一款通过 I²C 控制的 16 通道、12 位 PWM 驱动芯片。它最常被用作舵机驱动——一块小板子只占用单片机两个引脚,就能驱动多达 16 个舵机,这也是它成为机械臂、六足机器人和云台的标准选择的原因。
一块 PCA9685 能驱动多少个舵机?
每块板 16 个,而且一条 I²C 总线上最多可以级联 62 块板,共 992 个通道。实际的限制在于供电而不是通道数——16 个舵机同时动作可能要消耗好几安培的电流,这些电流必须来自独立的 V+ 端子,而不是单片机。
PCA9685 需要单独的电源吗?
需要,是给舵机用的。芯片的逻辑部分由单片机提供的 3.3–5 V 供电,但舵机从专用的 V+ 端子取电流——请把它接到一个能同时提供所有舵机堵转电流的电源上,否则它们会因电压下垂而抖动。
PCA9685 怎么接到 Arduino?
通过 I²C 连接——把 SDA 和 SCL 接到 Arduino 的 I²C 引脚上,再接 VCC 和 GND 给芯片的逻辑部分供电。然后把一个独立电源接到 V+ 端子上给舵机供电,并把每个舵机插到一组通道排针上。借助一个库(例如 Adafruit 的库),你就可以在代码里设置每个通道的角度。
PCA9685 板怎么级联?
每块板上都有六个焊接跳线焊盘,用来设定它的 I²C 地址。在每块板上桥接不同的组合,让每块板都有唯一的地址,然后把它们全部接到同样的两根 I²C 线上——一条总线最多可以挂 62 块板、992 个通道。
延伸阅读