ps:2022更新
pid详细解释
一般很少用增量式,都是用位置式,下文增量式可以不看
本文分为几个部分:
1.编码器
2.定时器输入捕获(把定时器初始化为编码器模式)
3.pid闭环控速度
编码器配置
编码器
1.概述
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200803205501941.png)
传感器-> 角速度或角位移------转化为------->电数字脉冲
2.原理
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200803210030315.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3l1bmRkdW4=,size_16,color_FFFFFF,t_70)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200811091554256.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3l1bmRkdW4=,size_16,color_FFFFFF,t_70)
四倍频技术
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200803210627265.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3l1bmRkdW4=,size_16,color_FFFFFF,t_70)
注意:
开始的时候一直很疑惑的一个点就是这边四倍频,如果按照这样操作,那么一个方波计数器将计数2次,而且ab两相那么就是计数4次,但是我们只出现了一个方波却记了4个,所以这边有问题。
//解决方案1:经过学长讲解,下文中TIM2配置编码器时候,psc=0x0需要改为0x03,这样能达到4分频,也只有在这种情况下才能准确计算出单位时间内的方波数量//(边沿触发cnt计数,分频没用)
定时器各参数含义
解决方案2:在下文Read_Encoder()函数中,将这句代码
case 2: Encoder_TIM= (short)TIM2 -> CNT; TIM2 -> CNT=0;break;
改成
case 2: Encoder_TIM=( (short)TIM2 -> CNT)/4; TIM2 -> CNT=0;break;
转速计算方法:用捕获值(一秒内输出的脉冲数)/编码器线数(转速一圈输出脉冲数)/电机减数比(内部电机转动圈数与电机输出轴转动圈数比,即减速齿轮比)
2.定时器输入捕获(把定时器初始化为编码器模式)
编码器定时器配置
void Encoder_Init_TIM2(void)
{
RCC->APB1ENR|=1<<0;
RCC->APB2ENR|=1<<2;
GPIOA->CRL&=0XFFFFFF00;
GPIOA->CRL|=0X00000044;
TIM2->PSC = 0x0;
TIM2->ARR = ENCODER_TIM_PERIOD-1;
TIM2->CCMR1 |= 1<<0;
TIM2->CCMR1 |= 1<<8;
TIM2->CCER |= 0<<1;
TIM2->CCER |= 0<<5;
TIM2->SMCR |= 3<<0;
TIM2->CR1 |= 0x01;
}
void Encoder_Init_TIM4(void)
{
RCC->APB1ENR|=1<<2;
RCC->APB2ENR|=1<<3;
GPIOB->CRL&=0X00FFFFFF;
GPIOB->CRL|=0X44000000;
TIM4->PSC = 0x0;
TIM4->ARR = ENCODER_TIM_PERIOD-1;
TIM4->CCMR1 |= 1<<0;
TIM4->CCMR1 |= 1<<8;
TIM4->CCER |= 0<<1;
TIM4->CCER |= 0<<5;
TIM4->SMCR |= 3<<0;
TIM4->CR1 |= 0x01;
}
3.pid闭环控速度
在main函数中调用
Timer3_Init(99,7199);
定时器3配置函数
void Timer3_Init(u16 arr,u16 psc)
{
RCC->APB1ENR|=1<<1;
TIM3->ARR=arr;
TIM3->PSC=psc;
TIM3->DIER|=1<<0;
TIM3->DIER|=1<<6;
TIM3->CR1|=0x01;
MY_NVIC_Init(1,3,TIM3_IRQn,2);
}
定时器3中断服务函数,其中用到的函数在下文实现
int Target_velocity=50;
int TIM3_IRQHandler(void)
{
if(TIM3->SR&0X0001)
{
TIM3->SR&=~(1<<0);
Encoder=Read_Encoder(2);
Led_Flash(100);
Moto1=Incremental_PI(Encoder,Target_velocity);
Xianfu_Pwm();
Set_Pwm(Moto1);
}
return 0;
}
读定时器cnt计数函数
int Read_Encoder(u8 TIMX)
{
int Encoder_TIM;
switch(TIMX)
{
case 2: Encoder_TIM= (short)TIM2 -> CNT; TIM2 -> CNT=0;break;
case 3: Encoder_TIM= (short)TIM3 -> CNT; TIM3 -> CNT=0;break;
case 4: Encoder_TIM= (short)TIM4 -> CNT; TIM4 -> CNT=0;break;
default: Encoder_TIM=0;
}
return Encoder_TIM;
}
增量式PID控制函数
int Incremental_PI (int Encoder,int Target)
{
float Kp=20,Ki=30;
static int Bias,Pwm,Last_bias;
Bias=Encoder-Target;
Pwm+=Kp*(Bias-Last_bias)+Ki*Bias;
Last_bias=Bias;
return Pwm;
}
位置式PID控制
int Position_PID (int Encoder,int Target)
{
float Position_KP=80,Position_KI=0.1,Position_KD=500;
static float Bias,Pwm,Integral_bias,Last_Bias;
Bias=Encoder-Target;
Integral_bias+=Bias;
Pwm=Position_KP*Bias+Position_KI*Integral_bias+Position_KD*(Bias-Last_Bias);
Last_Bias=Bias;
return Pwm;
}
void Set_Pwm(int moto1)
{
if(moto1>0) AIN2=1, AIN1=0;
else AIN2=0, AIN1=1;
PWMA=myabs(moto1);
}
void Xianfu_Pwm(void)
{
int Amplitude=7100;
if(Moto1<-Amplitude) Moto1=-Amplitude;
if(Moto1>Amplitude) Moto1=Amplitude;
}
源码:
电机速度闭环控制
电机位置闭环控制
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)