今天记录一下使用wiringPi库操作PCA9685控制舵机的方法。
首先抄袭一下舵机角度和占空比的关系:
一个周期为20ms的脉冲里面高电平持续的时间决定了舵机转动的角度,180度舵机对应关系如下:0.5ms--0度,1ms--45度,1.5ms--90度,2ms--135度,2.5ms--180度。
于是我封装了两个函数pca9685_init和pca_set_angle。
pca9685_init用来设置PWM频率。
pca_set_angle(int channel_id,int srv_type, int angle)函数的三个参数说明:
channel_id是通道id,pca9685有16个通道,channel_id的取值从0~15。
srv_type舵机类型,舵机的最大角度,取值一般无非90,180,270,360。
angle就是要设置的角度。
那如果你的舵机接在0通道,舵机是180度的,要装到90度,就是pca_set_angle(0,180,90)了。
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <unistd.h>
#include <stdio.h>
#define PCA9685_ADDR 0x40 //I2C总线地址
#define MODE1_ADDR 0x00 //MODE1寄存器地址
#define MODE2_ADDR 0x01 //MODE2寄存器地址
#define SVO_TYPE 180 //定义舵机最大旋转角度
#define AI 1 //定义是否开启自增功能
#define FR 50 //定义PWM频率
#define PRE_SCALE_REG 0XFE
int fd;
void pca9685_init(int ai, int freq)
{
int status;
int pwm_freq_reg_val;
fd = wiringPiI2CSetup(0x40);
status = wiringPiI2CReadReg8(fd, 0x00);
//修改频率前先切换到SLEEP状态
status = status | 0x10;
wiringPiI2CWriteReg8(fd, 0x00, status);
//写PRE_SCALE寄存器
pwm_freq_reg_val = 26214400 / 4096 / freq - 1;
wiringPiI2CWriteReg8(fd, PRE_SCALE_REG, pwm_freq_reg_val);
printf("frequence is set to %d.\n", FR);
//根据是否开启自增,切换到正常状态
if (ai == 0)
status = status & 0xCF;
else
status = status & 0xEF;
wiringPiI2CWriteReg8(fd, 0x00, status);
printf("Auto-increment is set to %d.\n", AI);
printf("pca9685 init complete.\n");
}
void pca_set_angle(int channel_id,int srv_type, int angle)
{
float ms;
int ledoff_reg;
ms = 0.5 + angle / srv_type * 2;
ledoff_reg = ms * 4096 / 20;
wiringPiI2CWriteReg16(fd, 0x08 + channel_id * 4, ledoff_reg);
};
int main(void)
{
wiringPiSetup();
pca9685_init(AI, FR);
usleep(500);
pca_set_angle(0, SVO_TYPE, 60);
return 0;
}