STM32F103控制PCA9685模块驱动多个舵机

STM32F103控制PCA9685模块驱动多个舵机
之前在做假⼿的控制时,驱动⽤的是舵机。因为要实现假⼿的多⾃由度动作,所以需要⽤到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);//中指
void Ring(void);//环指
void Little(void);//⼩拇指
void Wrist(void);//⼿腕
pca9685.c
#include"pca9685.h"
#include"myiic.h"
#include"delay.h"
#include"math.h"
void pca_write(u8 adrr,u8 data)//向PCA写数据,adrrd地址,data数据{
IIC_Start();
IIC_Send_Byte(pca_adrr);
IIC_Wait_Ack();
IIC_Send_Byte(adrr);
IIC_Wait_Ack();
IIC_Send_Byte(data);
IIC_Wait_Ack();
IIC_Stop();
}
u8 pca_read(u8 adrr)//从PCA读数据
{
u8 data;
IIC_Start();
IIC_Send_Byte(pca_adrr);
IIC_Wait_Ack();
IIC_Send_Byte(adrr);
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(pca_adrr|0x01);
IIC_Wait_Ack();
data=IIC_Read_Byte(0);
IIC_Stop();
return data;
}
void pca_setfreq(float freq)//设置PWM频率
{
u8 prescale,oldmode,newmode;
double prescaleval;
屏式电脑freq *=0.92;
prescaleval =25000000;
prescaleval /=4096;
马铃薯曲奇prescaleval /= freq;
prescaleval -=1;
prescale =floor(prescaleval +0.5f);
oldmode =pca_read(pca_mode1);//pca_mode1 0x0
newmode =(oldmode&0x7F)|0x10;// sleep  0x0&0x7f=0x0  0x0|0x10=0x10 pca_write(pca_mode1, newmode);// go to sleep  D4sleep写1
pca_write(pca_pre, prescale);// set the prescaler
//pca_pre 0xFE控制周期的寄存器,将计算过的预装载值放⼊
pca_write(pca_mode1, oldmode);//oldmode 0x0,D4写0退出sleep模式
delay_ms(2);
pca_write(pca_mode1, oldmode |0xa1);
//0x0|0xa1=10100001 D6使⽤内部时钟,D5内部地址读写后⾃动增加,D0响应0x70通⽤i2c地址}
void pca_setpwm(u8 num, u32 on, u32 off)
{
pca_write(LED0_ON_L+4*num,on);//
pca_write(LED0_ON_H+4*num,on>>8);
pca_write(LED0_OFF_L+4*num,off);
pca_write(LED0_OFF_H+4*num,off>>8);
}
/*num:舵机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的占空⽐。*/
void Thumb(void)//拇指伸展,缓慢增长,易于看到效果
{
u16 i=0;
for(i=800;i<=1622;i++)
{
pca_setpwm(1,0,i);
delay_ms(3);
}
}
void Index(void)//⾷指伸展{
u16 i=0;
for(i=675;i<=2200;i++)
{
pca_setpwm(2,0,i);
delay_ms(3);
}
}
void Middle(void)//中指伸展{
u16 i=0;
for(i=675;i<=2800;i++)
{
pca_setpwm(15,0,i);
delay_ms(3);
}
}
main.c
#include"led.h"
#include"delay.h"
#include"key.h"
#include"sys.h"
#include"usart.h"
#include"usmart.h"
#include"pca9685.h"
/************************************************
ALIENTEK战舰STM32开发板实验23
IIC 实验
技术⽀持:
淘宝店铺:
关注公众平台号:"正点原⼦",免费获取STM32资料。
⼴州市星翼电⼦科技有限公司
作者:正点原⼦ @ALIENTEK
************************************************/
int main(void)
{
// u8 key;
遥控激光笔
//  u16 c=0;
// u8 datatemp[SIZE];
delay_init();//延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级uart_init(115200);//串⼝初始化为115200
LED_Init();//初始化与LED连接的硬件接⼝
//LCD_Init();      //初始化LCD
KEY_Init();
IIC_Init();//IIC初始化
pca_write(pca_mode1,0x0);//写地址
pca_setfreq(330);//写舵机频率,模拟电机给50HZ,数字电机330HZ
while(1)
{
/*数值计算步骤:
脉冲时间0.5ms-2.5ms(占空⽐5%-12.5%),频率330HZ(周期3.03ms),分辨率4096
0°,0.5/3.03*4096=675
90°,1.5/3.03*4096=2017
180°,2.5/3.03*4096=3379
*/
for(j=0;j<100;j++)//控制三根⼿指舵机转动指定⾓度
{
Thumb();
Index();
Middle();
}
}
}
玻璃纤维滤筒可能写的有错误的地⽅,但程序是⾃⼰跑过的,没有问题。

本文发布于:2024-09-20 17:56:49,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/2/98767.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:舵机   设置   需要   数值   控制   变为
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议