直流电机控制
1. 编码器
1.1 简介
- 用来测量机械旋转或位移的传感器,能够测量机械部位在旋转或直线运动时的位移位置或速度等信息,并将其转换成一系列电信号
- 根据检测原理分为光电编码器(最广泛)、磁编码器(霍尔元件,精度较低)和感应式编码器(可靠性高,高端领域)
- 根据运动方式分为线性编码器和旋转编码器
- 根据编码类型分为增量式、绝对式、混合式
1.2 原理
- 分辨率:编码器能够分辨的最小单位
- 精度:编码器每个读数与转轴实际位置间的最大误差,通常用角度、角分或角秒来表示
- 最大响应频率:编码器每秒输出的脉冲数,单位是Hz
- 信号输出形式:直接输出/输入协议
1.3 定时器的编码器模式
1.3.1 程序逻辑
- 初始化定时器为编码器模式
void Encoder_Init_TIM3(void)
{
__HAL_RCC_TIM3_CLK_ENABLE();
GPIOA_TIM3_Init();
TIM3->PSC = 0x0;
TIM3->ARR = ENCODER_TIM_PERIOD-1;
TIM3->CCMR1 |= 1<<0;
TIM3->CCMR1 |= 1<<8;
TIM3->CCER |= 0<<1;
TIM3->CCER |= 0<<5;
TIM3->SMCR |= 3<<0;
TIM3->CR1 |= 0x01;
}
void GPIOA_TIM2_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1;
GPIO_Initure.Mode=GPIO_MODE_INPUT;
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
}
- 读取定时器中的脉冲数,通过读取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;
}
2. PID
2.1 简介
P(比例)I(积分)D(微分)
通过编码器的速度反馈,可以实时知道小车的速度是否慢了,然后利用目标速度与实际速度的误差代入算法,既可获得当前占空比,达到控制速度的效果
PID控制其实对偏差的控制过程
- PID算法连续公式
- 离散的PID公式
- 位置式PID:每次输出均与过去的状态有关,直接控制执行机构
- 增量式PID:实时性,无扰动切换,有稳态误差,溢出的影响大
2.2 原理
- 比例项:增大比例系数可以加快系统的响应、增大比例系数有助于减小静差
- 积分项:增大积分时间有利于减小超调,使系统稳定性增加,但是会增长消除静差的时间
- 微分项:具有超前调节的作用,抑制振荡
-
试凑法:先比例,再积分,最后微分 -
临界比例法:从大到小逐渐改变调节器的比例度,并且得到等幅度的震荡过程就叫做临界比例度 -
一般调节法:
- 输出不振荡 - 增大比例增益P
- 输出不振荡 - 减小积分时间常数Ti
- 输出不振荡 - 增大微分时间常数Td
(这三个任何一个过大都会造成系统振荡)
- 采样周期越短控制的效果越接近于连续,对于大多数算法缩短采样周期可使控制回路性能改善
- 但采样周期缩短时,频繁的采样必然会占用较多的计算工作时间,同时也会增加计算的负担
- 而对有些变化缓慢的受控对象无需很高的采样频率既可满意地进行跟踪,过多的采样反而没有多少实际意义
2.3 程序逻辑
一般把PID放在一个周期执行,比如定时器或定时的中断中,这里以定时器为例
- 在定时器中断中:读取编码器的值-PID计算-赋值PWM输出
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim==(&TIM3_Handler))
{
Encoder=Read_Encoder(2);
Moto1=Incremental_PI(Encoder,Target_velocity);
Xianfu_Pwm(&Moto1);
Set_Pwm(Moto1);
printf("AIN1=%d\tAIN2=%d\tMoto1=%d\tEncoder=%d\r\n",AIN1,AIN2,Moto1,Encoder);
}
}
- 增量式PI控制器
int Incremental_PI(int Encoder,int Target)
{
float Kp=20,Ki=30;
static int Bias,Pwm,Last_bias;
Bias=Target-Encoder;
Pwm+=Kp*(Bias-Last_bias)+Ki*Bias;
Last_bias=Bias;
return Pwm;
}
2.4 剖析PI控制器
-
中断函数中
- 读取编码器的值:Encoder(由于定时器每10ms中断一次,所以得到的值为每10ms的脉冲数)
- 调用速度PI控制器获得电机PWM变量:Motol
- 进行PWM限幅
- 赋值给PWM寄存器
-
读取编码器的值
- 初始化TIM为编码器模式(需要两个IO口)
- 读取TIM->CNT的值
-
增量PI控制器
- 该函数中的Kp和Ki需要直接在函数中修改
- 该函数的形参为编码器测量值:Encoder和目标速度:Target_velocity(目标速度的表示为每10msX个脉冲)
- 该函数的返回值是一个int的数据
- 补充知识点:static(静态局部变量的效果类似于局部变量)
-
PWM限幅
- 由于PWM的满幅是7200,不可以超过这个值
- 若Motol的绝对值超过7100,则将其修改为设定的最大值:7100
|