WAVEGO-PCA9685
来自Waveshare Wiki
PCA9685控制舵机
简介
- PCA9685是一款基于IIC总线控制,用于产生16路PWM信号的LED控制芯片,每一路LED输出端均可自由调节PWM波的频率和占空比。
- 舵机是一种位置(角度)伺服器,适用于需要连续控制角度变化并保持的控制系统。
- 本章主要介绍如何通过PCA9685改变PWM达到控制舵机转动的效果,在本产品的主控板ESP32上搭载有PCA9685芯片,舵机通过GPIO与ESP32通信。
- 通过本章的学习,您可以基本掌握如何通过PCA9685发送PWM信号控制舵机转动。
原理
- 在本产品中,板载ESP32通过IIC通信(GPIO32→SDA,GPIO33→SCL)控制PCA9685模块,然后PCA9685可以产生16路PWM脉冲信号控制舵机,通过调节PCA9685产生的16路PWM脉冲的占空比可调节舵机转动角度。
舵机编号及位置图示
- 该教程中的例程都用0号舵机实现,因此在运行例程前需要将0号舵机和1号舵机上的腿部连杆都拆卸下来。
注:白色摆臂不需要拆下来。
示例程序
代码
舵机简单转动
- 下载示例程序并解压。
- 打开示例程序,选择舵机简单转动并用Arduino IDE打开PCA9685_Servo1.ino。
- 用USB将WAVEGO和电脑连接,选择正确的参数和端口,上传程序。
- 程序运行时,通过
pwm.setPWM(0,0,286); pwm.setPWM(0,0,386);
转动舵机。 - 完整代码如下:
#include "Servo1.h" //导入库函数Servo1.h TwoWire IIC = TwoWire(0); //初始化IIC的IO口 Servo1 pwm = Servo1(0x40, IIC); //实例化pwm #define S_SCL 33 //定义时钟线的IO口为GPIO33 #define S_SDA 32 //定义数据线的IO口为GPIO32 #define LEG0 0 #define LEG1 1 #define SERVO_FREQ 50 void ServoSetup(){ IIC.begin(S_SDA, S_SCL, 26000000); //打开IIC通道 pwm.begin(); pwm.setOscillatorFrequency(26000000); pwm.setPWMFreq(SERVO_FREQ); //刷新频率为50Hz Wire.setClock(100000); //修改IIC的时钟频率为100KHz delay(10); } void setup() { ServoSetup(); pwm.setPWM(1,0,386); //为防止0号舵机摆动过程被1号舵机阻碍,需先将1号舵机设置到一定的角度给0号舵机预留空间 } void loop() { pwm.setPWM(0,0,286); delay(500); pwm.setPWM(0,0,386); delay(500); }
代码解析
- 舵机与PCA9685使用IIC通信。
TwoWire IIC = TwoWire(0); //初始化IIC的IO口 Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40, IIC); //实例化pwm #define S_SCL 33 //定义时钟线的IO口为GPIO33 #define S_SDA 32 //定义数据线的IO口为GPIO32
- 函数功能为打开IIC通道,初始化舵机。
void ServoSetup(){ IIC.begin(S_SDA, S_SCL, 26000000); //打开IIC通道 pwm.begin(); pwm.setOscillatorFrequency(26000000); pwm.setPWMFreq(SERVO_FREQ); //刷新频率为50Hz Wire.setClock(100000); //修改IIC的时钟频率为100KHz delay(10); }
- servoID为舵机编号,填入对应的舵机编号控制对应舵机,通过改变pwm转动舵机,pwm的取值为86~484,角度控制有对应角度及计算方法。
- 面向摆臂一侧,随着pwm值的增大,舵机摆臂做逆时针旋转。
- 为了防止0号舵机摆动过程中被1号舵机阻碍,需要将1号舵机设置摆动到一定位置确保0号舵机不会被阻碍。
pwm.setPWM(servoID, 0, pwm);
程序运行效果
- 0号舵机摆臂在45度范围内左右摆动。
舵机角度控制
- 选择舵机角度控制并用Arduino IDE打开PCA9685_Servo2.ino。
- 用USB将WAVEGO和电脑连接,选择正确的参数和端口,上传程序。
- 在该程序中,实现舵机转动的代码和舵机简单转动的代码一样,不同的是在这个程序中有介绍到如何用pwm控制舵机角度。
- 完整代码如下:
#include "Servo1.h" //导入头文件Servo1.h TwoWire IIC = TwoWire(0); //初始化IIC的IO口 Servo1 pwm = Servo1(0x40, IIC); //实例化pwm #define S_SCL 33 //定义时钟线的IO口为GPIO33 #define S_SDA 32 //定义数据线的IO口为GPIO32 #define LEG0 0 #define LEG1 1 #define SERVO_FREQ 50 void ServoSetup(){ IIC.begin(S_SDA, S_SCL, 26000000); //打开IIC通道 pwm.begin(); pwm.setOscillatorFrequency(26000000); pwm.setPWMFreq(SERVO_FREQ); //刷新频率为50Hz Wire.setClock(100000); //修改IIC的时钟频率为100KHz delay(10); } void setup() { ServoSetup(); pwm.setPWM(1,0,386); //为防止0号舵机摆动过程被1号舵机阻碍,需先将1号舵机设置到一定的角度给0号舵机预留空间 } void loop() { pwm.setPWM(0,0,86); //0号舵机摆到0度 delay(1000); pwm.setPWM(0,0,186); //0号舵机摆到45度 delay(1000); pwm.setPWM(0,0,286); //0号舵机摆到90度 delay(1000); pwm.setPWM(0,0,386); //0号舵机摆到135度 delay(1000); pwm.setPWM(0,0,484); //0号舵机摆到180度 delay(1000); }
代码解析
- 舵机的控制一般需要一个20ms的时基脉冲,该脉冲的高电平部分一般为0.5ms~2.5ms范围内的角度控制脉冲部分。PCA9685采用12位的寄存器来控制PWM占比,寄存器的值用以下方法计算:
脉冲高电平时间 角度 理论pwm 实际pwm 0.5ms 0度 0.5/20*(2^12-1)=102 86 1.0ms 45度 1.0/20*(2^12-1)=205 186 1.5ms 90度 1.5/20*(2^12-1)=307 286 2.0ms 135度 2.0/20*(2^12-1)=410 386 2.5ms 180度 2.5/20*(2^12-1)=512 484
程序运行效果
- 舵机摆臂依次摆动到0度、45度、90度、135度、180度,到达180度后又重新回到0度不停循环。
舵机步进操作
- >选择舵机角度控制并用Arduino IDE打开PCA9685_Servo3.ino,用USB将WAVEGO和电脑连接。
- 选择正确的参数和端口,上传程序。
- 在该程序中,定义了新的变量offset,该变量作为偏移值令pwm在到达484前不停+1,以实现步进操作。
- 完整代码如下:
#include "Servo1.h" //导入库函数Servo1.h TwoWire IIC = TwoWire(0); //初始化IIC的IO口 Servo1 pwm = Servo1(0x40, IIC); //实例化pwm #define S_SCL 33 //定义时钟线的IO口为GPIO33 #define S_SDA 32 //定义数据线的IO口为GPIO32 #define SERVO_FREQ 50 #define LEG0 0 #define LEG1 1 //设置舵机摆臂初始位置 int Position = 86; //初始化舵机 void ServoSetup(){ IIC.begin(S_SDA, S_SCL, 26000000); //打开IIC通道 pwm.begin(); pwm.setOscillatorFrequency(26000000); pwm.setPWMFreq(SERVO_FREQ); //刷新频率为50Hz Wire.setClock(100000); //修改IIC时钟频率为100KHz delay(10); } //转动舵机摆臂 void servoDebug(byte servoID, int offset){ if(Position<=484){ //原pwm小于等于484时开始步进操作 Position += offset; //舵机在原来的位置上摆动offset pwm.setPWM(servoID, 0, Position); //令指定舵机摆动到指定位置 }else{ Position = 86; pwm.setPWM(servoID,0,Position); } } void setup() { ServoSetup(); pwm.setPWM(1,0,386); //为防止0号舵机摆动过程被1号舵机阻碍,需先将1号舵机设置到一定的角度给0号舵机预留空间 pwm.setPWM(0,0,86); //初始化舵机摆臂位置 } void loop() { servoDebug(0,1); //0号舵机以偏移量1步进 delay(50); //系统暂停50ms }
代码解析
- 判断pwm是否小于等于484,为真时执行步进操作。
Position += offset;
pwm.setPWM(servoID, 0, Position)
为假时则执行else语句将pwm值重置为86。void servoDebug(byte servoID, int offset){ if(Position<=484){ //原pwm小于等于484时开始步进操作 Position += offset; //舵机在原来的位置上摆动offset pwm.setPWM(servoID, 0, Position); //令指定舵机摆动到指定位置 }else{ Position = 86; //原pwm大于或等于484时将pwm重置为86,并将舵机转到0度位置 pwm.setPWM(servoID,0,Position); } }
程序运行效果
- 舵机摆臂从0度开始摆动,以偏移值为1进行pwm不断+1的步进操作。
总结
- 通过本章可知,通过改变PCA9685发出的PWM信号可以对舵机进行控制。