之前在做假手的控制时,驱动用的是舵机。因为要实现假手的多自由度动作,所以需要用到8个舵机。这就需要主控板有多路pwm输出,所以在查阅了相关资料后,找到了PCA9685模块。因为网上对PCA9685模块的介绍很多,这里就不再详细介绍。贴上我认为介绍比较详细的链接:
其中主要是 PRE_SCALE寄存器
这个寄存器是用来设置周期的,具体原理可以不用管,只要记住这个公式:
其中osc_clock是时钟,根据上面的寄存器设置选择是内部25MHz时钟还是外部时钟; update_rate是频率,比如周期是20ms,那么频率就是50。 注意:实际应用中发现有误差,需要加入校准,要把udpate_rate乘以0.915。
舵机PWM输出引脚0-15,on:PWM上升计数值0-4096,off:PWM下降计数值0~4096
一个PWM周期分成4096份,由0开始+1计数,计到on时跳变为高电平,继续计数到off时
跳变为低电平,直到计满4096重新开始。所以当on不等于0时可作延时,当on等于0时,
off/4096的值就是PWM的占空比。
然后就是舵机的角度设置问题
以模拟舵机50HZ为例:(周期为20ms)
60°=0.5ms+(60/180)(2.5ms-0.5ms)=1.1666ms
1.1666ms/20ms=off/4096,off=239
数字舵机330HZ(对应周期为3.03ms)
60°时,off=1.1666/3.034096=1577
我用的是STM32F103ZET6,程序是在正点原子的IIC例程上写的
pca9685.h
#ifndef __PCA9685_H
#define __PCA9685_H
#include "myiic.h"
#define uint8 unsigned char
#define uint16 unsigned int
#define uint32 unsigned long
#define PCA9685_SUBADR1 0x2
#define PCA9685_SUBADR2 0x3
#define PCA9685_SUBADR3 0x4
#define pca_adrr 0x80
//#define pca_adrr 0x40
#define pca_mode1 0x0
#define pca_pre 0xFE //控制周期的寄存器
#define LED0_ON_L 0x6 //第0路
#define LED0_ON_H 0x7
#define LED0_OFF_L 0x8
#define LED0_OFF_H 0x9
#define ALLLED_ON_L 0xFA
#define ALLLED_ON_H 0xFB
#define ALLLED_OFF_L 0xFC
#define ALLLED_OFF_H 0xFD
void pca_write(u8 adrr,u8 data);
u8 pca_read(u8 adrr);
void pca_setfreq(float freq);
void pca_setpwm(u8 num, u32 on, u32 off);
void Thumb(void);//拇指
void Index(void);//食指
void Middle(void);//中指