目录
tb6612
TB6612是双驱动,也就是可以驱动两个电机;
下面分别是控制两个电机的IO口:
STBY接低电平处于待机模式,接高电平开始工作置1通过AIN1 AIN2,BIN1,BIN2 来控制正反转
VM:接12V以内电源
VCC:接5V电源
GND: 接电源负极
520编码电机
time.h配置定时器PWM模式和定时器编码模式
void encoder_PWM_Init(u16 arr,u16 psc);//TIM1的CH1和CH3作为A通道和B通道的PWM输出
void Encoder_Init_TIM2(void);//TIM2读取右轮的编码器值
void Encoder_Init_TIM3(void);//TIM3读取左轮的编码器值
int Read_Encoder(u8 TIMX);//编码器读取函数
void Encoder_Init(void);//与tb6612的AIN1 AIN2 BIN1 BIN2连接引脚的初始化
wheel.c将小车的前进、停止、左拐、右拐、掉头函数进行封装
extern int dianji_sudu_zuo,dianji_sudu_you;
extern int pwm_dianji_zuo,pwm_dianji_you;
void you_h(int sudu)
{
dianji_sudu_you=sudu;
GPIO_SetBits(GPIOB,GPIO_Pin_13);
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
TIM_SetCompare1(TIM1,sudu*1.4+pwm_dianji_you);
}
void you_q(int sudu)
{
dianji_sudu_you=sudu;
GPIO_SetBits(GPIOB,GPIO_Pin_12);
GPIO_ResetBits(GPIOB,GPIO_Pin_13);
TIM_SetCompare1(TIM1,sudu*1.4+pwm_dianji_you);
}
void zuo_q(int sudu)
{
dianji_sudu_zuo=sudu;
GPIO_SetBits(GPIOB,GPIO_Pin_1);
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
TIM_SetCompare3(TIM1,sudu*1.4+pwm_dianji_zuo);
}
void zuo_h(int sudu)
{
dianji_sudu_zuo=sudu;
GPIO_SetBits(GPIOB,GPIO_Pin_0);
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
TIM_SetCompare3(TIM1,sudu*1.4+pwm_dianji_zuo);
}
void zuoguai(int sudu_zuo,int sudu_you,int shijian)
{
zuo_h(sudu_zuo);
you_q(sudu_you);
delay_ms(shijian);
} //×ó¹Õ
void qianjin(int sudu_zuo,int sudu_you,int shijian)
{
zuo_q(sudu_zuo);
you_q(sudu_you);
delay_ms(shijian);
}
void stop(int time)
{
zuo_q(0);
you_q(0);
// GPIO_ResetBits(GPIOB,GPIO_Pin_11);
// GPIO_ResetBits(GPIOB,GPIO_Pin_12);
// GPIO_ResetBits(GPIOB,GPIO_Pin_0);
// GPIO_ResetBits(GPIOB,GPIO_Pin_1);
delay_ms(time);
}
void youguai(int sudu_zuo,int sudu_you,int shijian)
{
zuo_q(sudu_zuo);
you_h(sudu_you);
delay_ms(shijian);
} //ÓÒ¹Õ
void diaotou(int sudu,int shijian)
{
zuo_h(sudu);
you_q(sudu);
delay_ms(shijian);
} //µôÍ·
PI闭环
pid.c
#include "pid.h"
void pid_init(pid_t *pid,u32 max_out,u32 integral_limit,float kp,float ki,float kd)
{
pid->integral_limit=integral_limit;
pid->max_output=max_out;
pid->p=kp;
pid->i=ki;
pid->d=kd;
} //pidµÄ³õʼ»¯
static void abs_limit(float *a,float ABS_MAX)
{
if(*a>ABS_MAX)*a=ABS_MAX;
if(*a<-ABS_MAX)*a=-ABS_MAX;
}
//µç»ú±Õ»· PI
int pid_speed(pid_t *pid,int get,int set)
{
pid->get=get;//»ñÈ¡µ±Ç°Öµ
pid->set=set;//»ñÈ¡Ä¿±êÖµ
pid->err[NOW]=set-get;
pid->pout=pid->p*pid->err[NOW];//pÊä³ö¼ÆËã
pid->iout+=pid->i*pid->err[NOW];//iÊä³ö¼ÆËã
abs_limit(&(pid->iout),pid->integral_limit);//iÏÞ·ù
pid->out=pid->pout+pid->iout;//p+i
abs_limit(&(pid->out),pid->max_output);//p+iÏÞ·ù
pid->err[LAST]=pid->err[NOW];//µü´úÎó²î
return pid->out;
}
在main.c中使用TIM4中断周期性进行PID的运算,并将结果反馈到TIM_SetCompare()函数中,更新PWM的比较值。
void TIM4_IRQHandler(void) //TIM3??
{
if(TIM_GetITStatus(TIM4, TIM_IT_Update) == SET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
dianji_zuo_duqu=Read_Encoder(3);
dianji_you_duqu=Read_Encoder(2);
pwm_dianji_zuo=pid_speed(&speed_pid_zuo,abs(dianji_zuo_duqu),dianji_sudu_zuo);
pwm_dianji_you=pid_speed(&speed_pid_you,abs(dianji_you_duqu),dianji_sudu_you);
}
}
蓝牙
手机端发送"A""B"等字符,单片机串口2接收后将标志量更新
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET)
{
R_Data = USART_ReceiveData(USART3);//ÕâÐбíʾÊÕµ½µÄÊý¾Ý
if(R_Data=='A') USART3_Flag=1;
if(R_Data=='B') USART3_Flag=2;
if(R_Data=='C') USART3_Flag=3;
if(R_Data=='D') USART3_Flag=4;
if(R_Data=='E') USART3_Flag=5;
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
}
}
main.c中根据不同的标志量控制小车进行不同操作
while(1)
{
delay_ms(10);
if (USART3_Flag == 1)
{
USART3_Flag =0;
qianjin(120,120,160);
delay_ms(2000);
stop(3000);
}
if (USART3_Flag == 2)
{
USART3_Flag =0;
diaotou(120,740);
delay_ms(2000);
stop(3000);
}
if (USART3_Flag == 3)
{
USART3_Flag =0;
zuoguai(120,120,420);
delay_ms(2000);
stop(3000);
}
if (USART3_Flag == 4)
{
USART3_Flag =0;
youguai(120,120,410);
delay_ms(2000);
stop(3000);
}
}