|
回复 10楼able200330 的帖子
您好,我是这样处理的,将PID环放在一个定时器中断中,每2mS执行一次,以下是核心代码。加速度环的采集量是摆杆角度编码器,位置环的采集量是步进电机的正反脉冲计数,以此实现闭环控制。
void TIM2_IRQHandler(void)
{
if ( TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET )
{
TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update);
}
ADC_DOWN=268;
ADC_FULL=4075;
filter();//获取AD采样值并进行均值滤波
ADC_temp=(float)After_filter[0];
//ADC_temp=12;
if(ADC_temp
ADC_temp+=ADC_FULL;
f_angle=((ADC_temp-ADC_DOWN)/ADC_FULL)*360;
KP_L=(float)After_filter[1]/200;
KD_L=(float)After_filter[2]/200;
KP_V=(float)After_filter[3]/20;
KD_V=(float)After_filter[4]/40;
// ************ PID位置环,控制稳摆位置 ***********
float TimeCh1 = 0.002; // 采样时间(s)
//float Kp1 = 6.53, Ki1 =0.00, Kd1 = 2.84; // 比例系数、积分系数、微分系数
float Kp1, Ki1, Kd1;
Kp1=KP_L;Ki1=0.0;Kd1=KD_L;
float Setpoint1 = 0; // 设定目标值(degree)
float outMin1 = -3000, outMax1 =3000; // 输出上限、输出下限
float Input1 = (float)(CNTS*(0.0140625)); // 170; // 输入赋值
float error1 = Setpoint1 - Input1; // 偏差值
ITerm1+= (Ki1 * error1 * TimeCh1); // 计算积分项
ITerm1 = constrain(ITerm1, outMin1, outMax1); // 限定值域
float DTerm1 = Kd1 * (Input1 - lastInput1) / TimeCh1; // 计算微分项
Output1 = Kp1 * error1 + ITerm1 - DTerm1; // 计算输出值
Output1 = constrain(Output1, outMin1, outMax1); // 限定值域
ERR1=Output1/100;
lastInput1 = Input1; // 记录输入值
// ************ PID加速度环,控制稳摆 ***********
float TimeCh = 0.002; // 采样时间(s)
//float Kp = 142.0, Ki =0.00, Kd = 17.6; // 比例系数、积分系数、微分系数/
float Kp, Ki, Kd;
Kp=KP_V; Ki=0.0; Kd=KD_V;
float Setpoint = 180; // 设定目标值(degree)
float outMin = -20000, outMax =20000; // 输出上限、输出下限
float Input = f_angle; // 输入赋值
float error = Setpoint - Input - ERR1; // 偏差值
ITerm+= (Ki * error * TimeCh); // 计算积分项
ITerm = constrain(ITerm, outMin, outMax); // 限定值域
float DTerm = Kd * (Input - lastInput) / TimeCh; // 计算微分项
Output = Kp * error + ITerm - DTerm; // 计算输出值
Output = constrain(Output, outMin, outMax); // 限定值域
A_INPUT=Output;
lastInput = Input; // 记录输入值
} |
|