PID控制

PID通常和PWM一起使用。

PWM配置

void PWM_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(	RCC_APB2Periph_TIM8, ENABLE);
    RCC_AHB1PeriphClockCmd(	RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_CRC,ENABLE); 
    /*PC8 PWM管脚初始化*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 ;					
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_pp;	
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC , &GPIO_InitStructure);	

	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;


	TIM_DeInit(TIM8);
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_Period = 4000 - 1;
    TIM_TimeBaseInitStructure.TIM_Prescaler = 17;
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM8, &TIM_TimeBaseInitStructure);


    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 0;//初始占空比
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
    TIM_OC3Init(TIM8, &TIM_OCInitStructure);

    //TIM8 第3通道
    TIM_OC3PreloadConfig(TIM8, TIM_OCPreload_Enable);
	TIM_CtrlPWMOutputs(TIM8, ENABLE);
    TIM_ARRPreloadConfig(TIM8, ENABLE);
    TIM_Cmd(TIM8, ENABLE);
    

}

增量式PID初始化

typedef struct{
		float SetValue;				//设定值
		float ActualValue;		//实际值,控制量
		float Err;						//本次误差
	    float Err_Prev;				//上一次误差
		float Err_Last;				//最上次误差
		float Kp,Ki,Kd;				//比例系数,微分系数
}Inc_PID;									//增量式PID结构体定义


Inc_PID IncPID;
//增量式PID初始化
void Init_IncPID(void)
{
	IncPID.SetValue			= 0;
	IncPID.ActualValue	    = 0;
	IncPID.Err				= 0;
	IncPID.Err_Last			= 0;
	IncPID.Err_Prev			= 0;
	IncPID.Kp				= 5;
	IncPID.Ki				= 0;
	IncPID.Kd				= 3;
}
/*增量式PID控制*/
float IncPIDFun(float SetValue,float RetValue)
{
	float IncValue = 0.0;
	IncPID.SetValue = SetValue;
	IncPID.Err = IncPID.SetValue - RetValue;
	IncValue = IncPID.Kp * (IncPID.Err - IncPID.Err_Prev) + IncPID.Ki * IncPID.Err + IncPID.Kd * (IncPID.Err - 2*IncPID.Err_Prev + IncPID.Err_Last);
	IncPID.ActualValue += IncValue;
    IncPID.Err_Last = IncPID.Err_Prev;//下一次迭代  
    IncPID.Err_Prev = IncPID.Err;	
	return IncPID.ActualValue;
}

应用

int main(void)
{
    PWM_init();
    Init_IncPID();
    while(1)
    {
/*以下运用代码最好写在定时器中断中,通过更改KP,Ki,Kd的初始化来进行PID控制*/
        uint16_t PWMWidth = 0,PWM = 0;
        PWMWidth =IncPIDFun(SEtTemp,TemP);//控制温度(设定温度,实际温度)
        if(PWMWidth<0)
        {
            PWM=0;
        }
        else
        {
            PWM= PWMWidth ;
        }
        //修改占空比
        TIM_SetCompare3(TIM8,PWM);
        IWDG_Feed();//喂狗
    }
}

以下是位置式PID代码

typedef struct{
		float SetValue;				//设定值
		float ActualValue;		    //实际值
		float ControlValue;		    //生成控制量
		float Err;					//本次误差
		float Err_Last;				//上次误差
		float Kp,Ki,Kd;				//比例系数,微分系数		
		float Integral;				//误差累计
}Pos_PID;							//位置式PID结构体定义

Pos_PID PosPID;

void Init_PosPID(void)
{
	PosPID.SetValue 		= 0;
	PosPID.ActualValue 	    = 0;
	PosPID.ControlValue	    = 0;
	PosPID.Err				= 0;
	PosPID.Err_Last			= 0;
	PosPID.Integral			= 0;
	PosPID.Kp				= 5;
	PosPID.Ki				= 0.001;
	PosPID.Kd				= 3;
}

float PosPIDFun(float SetValue,float Value) 
{
	PosPID.SetValue = SetValue;
	PosPID.Err = PosPID.SetValue - Value;//PosPID.ActualValue;
	PosPID.Integral += PosPID.Err;
	PosPID.ControlValue = PosPID.Kp*PosPID.Err + PosPID.Ki*PosPID.Integral + PosPID.Kd*(IncPID.Err - PosPID.Err_Last);
	PosPID.Err_Last = PosPID.Err;
	PosPID.ActualValue = PosPID.ControlValue * 1.0;
	return PosPID.ActualValue;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值